Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / content / browser / renderer_host / compositor_impl_android.cc
index 8c14b64..bc2709c 100644 (file)
@@ -6,25 +6,27 @@
 
 #include <android/bitmap.h>
 #include <android/native_window_jni.h>
-#include <map>
 
 #include "base/android/jni_android.h"
 #include "base/android/scoped_java_ref.h"
 #include "base/bind.h"
 #include "base/command_line.h"
+#include "base/containers/hash_tables.h"
 #include "base/lazy_instance.h"
 #include "base/logging.h"
+#include "base/memory/weak_ptr.h"
 #include "base/single_thread_task_runner.h"
 #include "base/synchronization/lock.h"
 #include "base/threading/thread.h"
+#include "base/threading/thread_checker.h"
+#include "cc/base/switches.h"
 #include "cc/input/input_handler.h"
 #include "cc/layers/layer.h"
 #include "cc/output/compositor_frame.h"
 #include "cc/output/context_provider.h"
 #include "cc/output/output_surface.h"
-#include "cc/resources/scoped_ui_resource.h"
-#include "cc/resources/ui_resource_bitmap.h"
 #include "cc/trees/layer_tree_host.h"
+#include "content/browser/android/child_process_launcher_android.h"
 #include "content/browser/gpu/browser_gpu_channel_host_factory.h"
 #include "content/browser/gpu/gpu_surface_tracker.h"
 #include "content/common/gpu/client/command_buffer_proxy_impl.h"
 #include "content/common/gpu/client/gpu_channel_host.h"
 #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
 #include "content/common/gpu/gpu_process_launch_causes.h"
+#include "content/common/host_shared_bitmap_manager.h"
 #include "content/public/browser/android/compositor_client.h"
-#include "content/public/common/content_switches.h"
-#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
+#include "gpu/command_buffer/client/gles2_interface.h"
 #include "third_party/khronos/GLES2/gl2.h"
 #include "third_party/khronos/GLES2/gl2ext.h"
+#include "third_party/skia/include/core/SkMallocPixelRef.h"
+#include "ui/base/android/window_android.h"
 #include "ui/gfx/android/device_display_info.h"
-#include "ui/gfx/android/java_bitmap.h"
 #include "ui/gfx/frame_time.h"
+#include "ui/gl/android/surface_texture.h"
+#include "ui/gl/android/surface_texture_tracker.h"
 #include "webkit/common/gpu/context_provider_in_process.h"
 #include "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h"
 
-namespace gfx {
-class JavaBitmap;
-}
-
 namespace {
 
-// Used for drawing directly to the screen. Bypasses resizing and swaps.
-class DirectOutputSurface : public cc::OutputSurface {
- public:
-  DirectOutputSurface(
-      const scoped_refptr<cc::ContextProvider>& context_provider)
-      : cc::OutputSurface(context_provider) {
-    capabilities_.adjust_deadline_for_parent = false;
-  }
-
-  virtual void Reshape(gfx::Size size, float scale_factor) OVERRIDE {
-    surface_size_ = size;
-  }
-  virtual void SwapBuffers(cc::CompositorFrame*) OVERRIDE {
-    context_provider_->Context3d()->shallowFlushCHROMIUM();
-  }
-};
+const unsigned int kMaxSwapBuffers = 2U;
 
 // Used to override capabilities_.adjust_deadline_for_parent to false
 class OutputSurfaceWithoutParent : public cc::OutputSurface {
  public:
-  OutputSurfaceWithoutParent(
-      const scoped_refptr<
-        content::ContextProviderCommandBuffer>& context_provider)
+  OutputSurfaceWithoutParent(const scoped_refptr<
+      content::ContextProviderCommandBuffer>& context_provider,
+      base::WeakPtr<content::CompositorImpl> compositor_impl)
       : cc::OutputSurface(context_provider) {
     capabilities_.adjust_deadline_for_parent = false;
+    compositor_impl_ = compositor_impl;
+    main_thread_ = base::MessageLoopProxy::current();
   }
 
   virtual void SwapBuffers(cc::CompositorFrame* frame) OVERRIDE {
-    content::WebGraphicsContext3DCommandBufferImpl* command_buffer_context =
-        static_cast<content::WebGraphicsContext3DCommandBufferImpl*>(
-            context_provider_->Context3d());
+    content::ContextProviderCommandBuffer* provider_command_buffer =
+        static_cast<content::ContextProviderCommandBuffer*>(
+            context_provider_.get());
     content::CommandBufferProxyImpl* command_buffer_proxy =
-        command_buffer_context->GetCommandBufferProxy();
+        provider_command_buffer->GetCommandBufferProxy();
     DCHECK(command_buffer_proxy);
     command_buffer_proxy->SetLatencyInfo(frame->metadata.latency_info);
 
     OutputSurface::SwapBuffers(frame);
   }
+
+  virtual bool BindToClient(cc::OutputSurfaceClient* client) OVERRIDE {
+    if (!OutputSurface::BindToClient(client))
+      return false;
+
+    main_thread_->PostTask(
+        FROM_HERE,
+        base::Bind(&content::CompositorImpl::PopulateGpuCapabilities,
+                   compositor_impl_,
+                   context_provider_->ContextCapabilities().gpu));
+
+    return true;
+  }
+
+  scoped_refptr<base::MessageLoopProxy> main_thread_;
+  base::WeakPtr<content::CompositorImpl> compositor_impl_;
 };
 
+class SurfaceTextureTrackerImpl : public gfx::SurfaceTextureTracker {
+ public:
+  SurfaceTextureTrackerImpl() : next_surface_texture_id_(1) {
+    thread_checker_.DetachFromThread();
+  }
+
+  // Overridden from gfx::SurfaceTextureTracker:
+  virtual scoped_refptr<gfx::SurfaceTexture> AcquireSurfaceTexture(
+      int primary_id,
+      int secondary_id) OVERRIDE {
+    base::AutoLock lock(surface_textures_lock_);
+    SurfaceTextureMapKey key(primary_id, secondary_id);
+    SurfaceTextureMap::iterator it = surface_textures_.find(key);
+    if (it == surface_textures_.end())
+      return scoped_refptr<gfx::SurfaceTexture>();
+    scoped_refptr<gfx::SurfaceTexture> surface_texture = it->second;
+    surface_textures_.erase(it);
+    return surface_texture;
+  }
+
+  int AddSurfaceTexture(gfx::SurfaceTexture* surface_texture,
+                        int child_process_id) {
+    DCHECK(thread_checker_.CalledOnValidThread());
+    int surface_texture_id = next_surface_texture_id_++;
+    if (next_surface_texture_id_ == INT_MAX)
+      next_surface_texture_id_ = 1;
+
+    base::AutoLock lock(surface_textures_lock_);
+    SurfaceTextureMapKey key(surface_texture_id, child_process_id);
+    DCHECK(surface_textures_.find(key) == surface_textures_.end());
+    surface_textures_[key] = surface_texture;
+    content::RegisterChildProcessSurfaceTexture(
+        surface_texture_id,
+        child_process_id,
+        surface_texture->j_surface_texture().obj());
+    return surface_texture_id;
+  }
+
+  void RemoveAllSurfaceTextures(int child_process_id) {
+    DCHECK(thread_checker_.CalledOnValidThread());
+    base::AutoLock lock(surface_textures_lock_);
+    SurfaceTextureMap::iterator it = surface_textures_.begin();
+    while (it != surface_textures_.end()) {
+      if (it->first.second == child_process_id) {
+        content::UnregisterChildProcessSurfaceTexture(it->first.first,
+                                                      it->first.second);
+        surface_textures_.erase(it++);
+      } else {
+        ++it;
+      }
+    }
+  }
+
+ private:
+  typedef std::pair<int, int> SurfaceTextureMapKey;
+  typedef base::hash_map<SurfaceTextureMapKey,
+                         scoped_refptr<gfx::SurfaceTexture> >
+      SurfaceTextureMap;
+  SurfaceTextureMap surface_textures_;
+  mutable base::Lock surface_textures_lock_;
+  int next_surface_texture_id_;
+  base::ThreadChecker thread_checker_;
+};
+base::LazyInstance<SurfaceTextureTrackerImpl> g_surface_texture_tracker =
+    LAZY_INSTANCE_INITIALIZER;
+
 static bool g_initialized = false;
-static base::Thread* g_impl_thread = NULL;
 
 } // anonymous namespace
 
 namespace content {
 
-typedef std::map<int, base::android::ScopedJavaGlobalRef<jobject> >
-    SurfaceMap;
-static base::LazyInstance<SurfaceMap>
-    g_surface_map = LAZY_INSTANCE_INITIALIZER;
-static base::LazyInstance<base::Lock> g_surface_map_lock;
-
 // static
-Compositor* Compositor::Create(CompositorClient* client) {
-  return client ? new CompositorImpl(client) : NULL;
+Compositor* Compositor::Create(CompositorClient* client,
+                               gfx::NativeWindow root_window) {
+  return client ? new CompositorImpl(client, root_window) : NULL;
 }
 
 // static
 void Compositor::Initialize() {
   DCHECK(!CompositorImpl::IsInitialized());
+  // SurfaceTextureTracker instance must be set before we create a GPU thread
+  // that could be using it to initialize GLImage instances.
+  gfx::SurfaceTextureTracker::InitInstance(g_surface_texture_tracker.Pointer());
   g_initialized = true;
 }
 
@@ -120,46 +187,186 @@ bool CompositorImpl::IsInitialized() {
 }
 
 // static
-bool CompositorImpl::IsThreadingEnabled() {
-  return g_impl_thread;
+int CompositorImpl::CreateSurfaceTexture(int child_process_id) {
+  // Note: this needs to be 0 as the surface texture implemenation will take
+  // ownership of the texture and call glDeleteTextures when the GPU service
+  // attaches the surface texture to a real texture id. glDeleteTextures
+  // silently ignores 0.
+  const int kDummyTextureId = 0;
+  scoped_refptr<gfx::SurfaceTexture> surface_texture =
+      gfx::SurfaceTexture::Create(kDummyTextureId);
+  return g_surface_texture_tracker.Pointer()->AddSurfaceTexture(
+      surface_texture.get(), child_process_id);
 }
 
 // static
-jobject CompositorImpl::GetSurface(int surface_id) {
-  base::AutoLock lock(g_surface_map_lock.Get());
-  SurfaceMap* surfaces = g_surface_map.Pointer();
-  SurfaceMap::iterator it = surfaces->find(surface_id);
-  jobject jsurface = it == surfaces->end() ? NULL : it->second.obj();
-
-  LOG_IF(WARNING, !jsurface) << "No surface for surface id " << surface_id;
-  return jsurface;
+void CompositorImpl::DestroyAllSurfaceTextures(int child_process_id) {
+  g_surface_texture_tracker.Pointer()->RemoveAllSurfaceTextures(
+      child_process_id);
 }
 
-CompositorImpl::CompositorImpl(CompositorClient* client)
+CompositorImpl::CompositorImpl(CompositorClient* client,
+                               gfx::NativeWindow root_window)
     : root_layer_(cc::Layer::Create()),
       has_transparent_background_(false),
+      device_scale_factor_(1),
       window_(NULL),
       surface_id_(0),
       client_(client),
+      root_window_(root_window),
+      did_post_swapbuffers_(false),
+      ignore_schedule_composite_(false),
+      needs_composite_(false),
+      needs_animate_(false),
+      will_composite_immediately_(false),
+      composite_on_vsync_trigger_(DO_NOT_COMPOSITE),
+      pending_swapbuffers_(0U),
       weak_factory_(this) {
   DCHECK(client);
+  DCHECK(root_window);
   ImageTransportFactoryAndroid::AddObserver(this);
+  root_window->AttachCompositor(this);
 }
 
 CompositorImpl::~CompositorImpl() {
+  root_window_->DetachCompositor();
   ImageTransportFactoryAndroid::RemoveObserver(this);
   // Clean-up any surface references.
   SetSurface(NULL);
 }
 
-void CompositorImpl::Composite() {
-  if (host_)
-    host_->Composite(gfx::FrameTime::Now());
+void CompositorImpl::PostComposite(CompositingTrigger trigger) {
+  DCHECK(needs_composite_);
+  DCHECK(trigger == COMPOSITE_IMMEDIATELY || trigger == COMPOSITE_EVENTUALLY);
+
+  if (will_composite_immediately_ ||
+      (trigger == COMPOSITE_EVENTUALLY && WillComposite())) {
+    // We will already composite soon enough.
+    DCHECK(WillComposite());
+    return;
+  }
+
+  if (DidCompositeThisFrame()) {
+    DCHECK(!WillCompositeThisFrame());
+    if (composite_on_vsync_trigger_ != COMPOSITE_IMMEDIATELY) {
+      composite_on_vsync_trigger_ = trigger;
+      root_window_->RequestVSyncUpdate();
+    }
+    DCHECK(WillComposite());
+    return;
+  }
+
+  base::TimeDelta delay;
+  if (trigger == COMPOSITE_IMMEDIATELY) {
+    will_composite_immediately_ = true;
+    composite_on_vsync_trigger_ = DO_NOT_COMPOSITE;
+  } else {
+    DCHECK(!WillComposite());
+    const base::TimeDelta estimated_composite_time = vsync_period_ / 4;
+    const base::TimeTicks now = base::TimeTicks::Now();
+
+    if (!last_vsync_.is_null() && (now - last_vsync_) < vsync_period_) {
+      base::TimeTicks next_composite =
+          last_vsync_ + vsync_period_ - estimated_composite_time;
+      if (next_composite < now) {
+        // It's too late, we will reschedule composite as needed on the next
+        // vsync.
+        composite_on_vsync_trigger_ = COMPOSITE_EVENTUALLY;
+        root_window_->RequestVSyncUpdate();
+        DCHECK(WillComposite());
+        return;
+      }
+
+      delay = next_composite - now;
+    }
+  }
+  TRACE_EVENT2("cc", "CompositorImpl::PostComposite",
+               "trigger", trigger,
+               "delay", delay.InMillisecondsF());
+
+  DCHECK(composite_on_vsync_trigger_ == DO_NOT_COMPOSITE);
+  if (current_composite_task_)
+    current_composite_task_->Cancel();
+
+  // Unretained because we cancel the task on shutdown.
+  current_composite_task_.reset(new base::CancelableClosure(
+      base::Bind(&CompositorImpl::Composite, base::Unretained(this), trigger)));
+  base::MessageLoop::current()->PostDelayedTask(
+      FROM_HERE, current_composite_task_->callback(), delay);
+}
+
+void CompositorImpl::Composite(CompositingTrigger trigger) {
+  BrowserGpuChannelHostFactory* factory =
+      BrowserGpuChannelHostFactory::instance();
+  if (!factory->GetGpuChannel() || factory->GetGpuChannel()->IsLost()) {
+    CauseForGpuLaunch cause =
+        CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE;
+    factory->EstablishGpuChannel(cause,
+                                 base::Bind(&CompositorImpl::ScheduleComposite,
+                                            weak_factory_.GetWeakPtr()));
+    return;
+  }
+
+  DCHECK(host_);
+  DCHECK(trigger == COMPOSITE_IMMEDIATELY || trigger == COMPOSITE_EVENTUALLY);
+  DCHECK(needs_composite_);
+  DCHECK(!DidCompositeThisFrame());
+
+  if (trigger == COMPOSITE_IMMEDIATELY)
+    will_composite_immediately_ = false;
+
+  DCHECK_LE(pending_swapbuffers_, kMaxSwapBuffers);
+  if (pending_swapbuffers_ == kMaxSwapBuffers) {
+    TRACE_EVENT0("compositor", "CompositorImpl_SwapLimit");
+    return;
+  }
+
+  // Reset state before Layout+Composite since that might create more
+  // requests to Composite that we need to respect.
+  needs_composite_ = false;
+
+  // Only allow compositing once per vsync.
+  current_composite_task_->Cancel();
+  DCHECK(DidCompositeThisFrame() && !WillComposite());
+
+  // Ignore ScheduleComposite() from layer tree changes during layout and
+  // animation updates that will already be reflected in the current frame
+  // we are about to draw.
+  ignore_schedule_composite_ = true;
+
+  const base::TimeTicks frame_time = gfx::FrameTime::Now();
+  if (needs_animate_) {
+    needs_animate_ = false;
+    root_window_->Animate(frame_time);
+  }
+  ignore_schedule_composite_ = false;
+
+  did_post_swapbuffers_ = false;
+  host_->Composite(frame_time);
+  if (did_post_swapbuffers_)
+    pending_swapbuffers_++;
+
+  // Need to track vsync to avoid compositing more than once per frame.
+  root_window_->RequestVSyncUpdate();
+}
+
+UIResourceProvider& CompositorImpl::GetUIResourceProvider() {
+  return ui_resource_provider_;
+}
+
+ui::SystemUIResourceManager& CompositorImpl::GetSystemUIResourceManager() {
+  return ui_resource_provider_.GetSystemUIResourceManager();
 }
 
 void CompositorImpl::SetRootLayer(scoped_refptr<cc::Layer> root_layer) {
-  root_layer_->RemoveAllChildren();
-  root_layer_->AddChild(root_layer);
+  if (subroot_layer_) {
+    subroot_layer_->RemoveFromParent();
+    subroot_layer_ = NULL;
+  }
+  if (root_layer) {
+    subroot_layer_ = root_layer;
+    root_layer_->AddChild(root_layer);
+  }
 }
 
 void CompositorImpl::SetWindowSurface(ANativeWindow* window) {
@@ -189,62 +396,86 @@ void CompositorImpl::SetSurface(jobject surface) {
   base::android::ScopedJavaLocalRef<jobject> j_surface(env, surface);
 
   // First, cleanup any existing surface references.
-  if (surface_id_) {
-    DCHECK(g_surface_map.Get().find(surface_id_) !=
-           g_surface_map.Get().end());
-    base::AutoLock lock(g_surface_map_lock.Get());
-    g_surface_map.Get().erase(surface_id_);
-  }
+  if (surface_id_)
+    content::UnregisterViewSurface(surface_id_);
   SetWindowSurface(NULL);
 
   // Now, set the new surface if we have one.
   ANativeWindow* window = NULL;
-  if (surface)
+  if (surface) {
+    // Note: This ensures that any local references used by
+    // ANativeWindow_fromSurface are released immediately. This is needed as a
+    // workaround for https://code.google.com/p/android/issues/detail?id=68174
+    base::android::ScopedJavaLocalFrame scoped_local_reference_frame(env);
     window = ANativeWindow_fromSurface(env, surface);
+  }
   if (window) {
     SetWindowSurface(window);
     ANativeWindow_release(window);
-    {
-      base::AutoLock lock(g_surface_map_lock.Get());
-      g_surface_map.Get().insert(std::make_pair(surface_id_, j_surface));
-    }
+    content::RegisterViewSurface(surface_id_, j_surface.obj());
   }
 }
 
 void CompositorImpl::SetVisible(bool visible) {
   if (!visible) {
-    ui_resource_map_.clear();
+    DCHECK(host_);
+    // Look for any layers that were attached to the root for readback
+    // and are waiting for Composite() to happen.
+    bool readback_pending = false;
+    for (size_t i = 0; i < root_layer_->children().size(); ++i) {
+      if (root_layer_->children()[i]->HasCopyRequest()) {
+        readback_pending = true;
+        break;
+      }
+    }
+    if (readback_pending) {
+      ignore_schedule_composite_ = true;
+      host_->Composite(base::TimeTicks::Now());
+      ignore_schedule_composite_ = false;
+    }
+    if (WillComposite())
+      CancelComposite();
+    ui_resource_provider_.SetLayerTreeHost(NULL);
     host_.reset();
-    client_->UIResourcesAreInvalid();
   } else if (!host_) {
+    DCHECK(!WillComposite());
+    needs_composite_ = false;
+    pending_swapbuffers_ = 0;
     cc::LayerTreeSettings settings;
     settings.refresh_rate = 60.0;
     settings.impl_side_painting = false;
     settings.allow_antialiasing = false;
     settings.calculate_top_controls_position = false;
     settings.top_controls_height = 0.f;
-    settings.use_memory_management = false;
     settings.highp_threshold_min = 2048;
 
-    scoped_refptr<base::SingleThreadTaskRunner> impl_thread_task_runner =
-        g_impl_thread ? g_impl_thread->message_loop()->message_loop_proxy()
-                      : NULL;
-
-    host_ = cc::LayerTreeHost::Create(
-        this, NULL, settings, impl_thread_task_runner);
+    base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+    settings.initial_debug_state.SetRecordRenderingStats(
+        command_line->HasSwitch(cc::switches::kEnableGpuBenchmarking));
+    settings.initial_debug_state.show_fps_counter =
+        command_line->HasSwitch(cc::switches::kUIShowFPSCounter);
+    // TODO(enne): Update this this compositor to use the scheduler.
+    settings.single_thread_proxy_scheduler = false;
+
+    host_ = cc::LayerTreeHost::CreateSingleThreaded(
+        this,
+        this,
+        HostSharedBitmapManager::current(),
+        settings,
+        base::MessageLoopProxy::current());
     host_->SetRootLayer(root_layer_);
 
     host_->SetVisible(true);
     host_->SetLayerTreeHostClientReady();
     host_->SetViewportSize(size_);
     host_->set_has_transparent_background(has_transparent_background_);
-    // Need to recreate the UI resources because a new LayerTreeHost has been
-    // created.
-    client_->DidLoseUIResources();
+    host_->SetDeviceScaleFactor(device_scale_factor_);
+    ui_resource_provider_.SetLayerTreeHost(host_.get());
   }
 }
 
 void CompositorImpl::setDeviceScaleFactor(float factor) {
+  device_scale_factor_ = factor;
   if (host_)
     host_->SetDeviceScaleFactor(factor);
 }
@@ -259,113 +490,27 @@ void CompositorImpl::SetWindowBounds(const gfx::Size& size) {
   root_layer_->SetBounds(size);
 }
 
-bool CompositorImpl::CompositeAndReadback(void *pixels, const gfx::Rect& rect) {
+void CompositorImpl::SetHasTransparentBackground(bool flag) {
+  has_transparent_background_ = flag;
   if (host_)
-    return host_->CompositeAndReadback(pixels, rect);
-  else
-    return false;
+    host_->set_has_transparent_background(flag);
 }
 
-cc::UIResourceId CompositorImpl::GenerateUIResource(
-    const cc::UIResourceBitmap& bitmap) {
-  if (!host_)
-    return 0;
-  scoped_ptr<cc::ScopedUIResource> ui_resource =
-      cc::ScopedUIResource::Create(host_.get(), bitmap);
-  cc::UIResourceId id = ui_resource->id();
-  ui_resource_map_.set(id, ui_resource.Pass());
-  return id;
-}
-
-void CompositorImpl::DeleteUIResource(cc::UIResourceId resource_id) {
-  UIResourceMap::iterator it = ui_resource_map_.find(resource_id);
-  if (it != ui_resource_map_.end())
-    ui_resource_map_.erase(it);
-}
-
-WebKit::WebGLId CompositorImpl::GenerateTexture(gfx::JavaBitmap& bitmap) {
-  unsigned int texture_id = BuildBasicTexture();
-  WebKit::WebGraphicsContext3D* context =
-      ImageTransportFactoryAndroid::GetInstance()->GetContext3D();
-  if (texture_id == 0 || context->isContextLost() ||
-      !context->makeContextCurrent())
-    return 0;
-  WebKit::WebGLId format = GetGLFormatForBitmap(bitmap);
-  WebKit::WebGLId type = GetGLTypeForBitmap(bitmap);
-
-  context->texImage2D(GL_TEXTURE_2D,
-                      0,
-                      format,
-                      bitmap.size().width(),
-                      bitmap.size().height(),
-                      0,
-                      format,
-                      type,
-                      bitmap.pixels());
-  context->shallowFlushCHROMIUM();
-  return texture_id;
-}
-
-WebKit::WebGLId CompositorImpl::GenerateCompressedTexture(gfx::Size& size,
-                                                          int data_size,
-                                                          void* data) {
-  unsigned int texture_id = BuildBasicTexture();
-  WebKit::WebGraphicsContext3D* context =
-        ImageTransportFactoryAndroid::GetInstance()->GetContext3D();
-  if (texture_id == 0 || context->isContextLost() ||
-      !context->makeContextCurrent())
-    return 0;
-  context->compressedTexImage2D(GL_TEXTURE_2D,
-                                0,
-                                GL_ETC1_RGB8_OES,
-                                size.width(),
-                                size.height(),
-                                0,
-                                data_size,
-                                data);
-  context->shallowFlushCHROMIUM();
-  return texture_id;
-}
-
-void CompositorImpl::DeleteTexture(WebKit::WebGLId texture_id) {
-  WebKit::WebGraphicsContext3D* context =
-      ImageTransportFactoryAndroid::GetInstance()->GetContext3D();
-  if (context->isContextLost() || !context->makeContextCurrent())
+void CompositorImpl::SetNeedsComposite() {
+  if (!host_.get())
     return;
-  context->deleteTexture(texture_id);
-  context->shallowFlushCHROMIUM();
-}
-
-bool CompositorImpl::CopyTextureToBitmap(WebKit::WebGLId texture_id,
-                                         gfx::JavaBitmap& bitmap) {
-  return CopyTextureToBitmap(texture_id, gfx::Rect(bitmap.size()), bitmap);
-}
-
-bool CompositorImpl::CopyTextureToBitmap(WebKit::WebGLId texture_id,
-                                         const gfx::Rect& sub_rect,
-                                         gfx::JavaBitmap& bitmap) {
-  // The sub_rect should match the bitmap size.
-  DCHECK(bitmap.size() == sub_rect.size());
-  if (bitmap.size() != sub_rect.size() || texture_id == 0) return false;
+  DCHECK(!needs_composite_ || WillComposite());
 
-  GLHelper* helper = ImageTransportFactoryAndroid::GetInstance()->GetGLHelper();
-  helper->ReadbackTextureSync(texture_id,
-                              sub_rect,
-                              static_cast<unsigned char*> (bitmap.pixels()));
-  return true;
+  needs_composite_ = true;
+  PostComposite(COMPOSITE_IMMEDIATELY);
 }
 
 static scoped_ptr<WebGraphicsContext3DCommandBufferImpl>
 CreateGpuProcessViewContext(
-    const WebKit::WebGraphicsContext3D::Attributes attributes,
-    int surface_id,
-    base::WeakPtr<CompositorImpl> compositor_impl) {
-  BrowserGpuChannelHostFactory* factory =
-      BrowserGpuChannelHostFactory::instance();
-  scoped_refptr<GpuChannelHost> gpu_channel_host(factory->EstablishGpuChannelSync(
-      CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE));
-  if (!gpu_channel_host)
-    return scoped_ptr<WebGraphicsContext3DCommandBufferImpl>();
+    const scoped_refptr<GpuChannelHost>& gpu_channel_host,
+    const blink::WebGraphicsContext3D::Attributes attributes,
+    int surface_id) {
+  DCHECK(gpu_channel_host);
 
   GURL url("chrome://gpu/Compositor::createContext3D");
   static const size_t kBytesPerPixel = 4;
@@ -381,121 +526,166 @@ CreateGpuProcessViewContext(
   limits.max_transfer_buffer_size = std::min(
       3 * full_screen_texture_size_in_bytes, kDefaultMaxTransferBufferSize);
   limits.mapped_memory_reclaim_limit = 2 * 1024 * 1024;
+  bool lose_context_when_out_of_memory = true;
   return make_scoped_ptr(
       new WebGraphicsContext3DCommandBufferImpl(surface_id,
                                                 url,
                                                 gpu_channel_host.get(),
-                                                compositor_impl,
                                                 attributes,
-                                                false,
+                                                lose_context_when_out_of_memory,
                                                 limits,
-                                                true));
+                                                NULL));
+}
+
+void CompositorImpl::Layout() {
+  ignore_schedule_composite_ = true;
+  client_->Layout();
+  ignore_schedule_composite_ = false;
 }
 
-scoped_ptr<cc::OutputSurface> CompositorImpl::CreateOutputSurface(
-    bool fallback) {
-  WebKit::WebGraphicsContext3D::Attributes attrs;
+void CompositorImpl::RequestNewOutputSurface(bool fallback) {
+  BrowserGpuChannelHostFactory* factory =
+      BrowserGpuChannelHostFactory::instance();
+  if (!factory->GetGpuChannel() || factory->GetGpuChannel()->IsLost()) {
+    CauseForGpuLaunch cause =
+        CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE;
+    factory->EstablishGpuChannel(
+        cause,
+        base::Bind(&CompositorImpl::CreateOutputSurface,
+                   weak_factory_.GetWeakPtr(),
+                   fallback));
+    return;
+  }
+
+  CreateOutputSurface(fallback);
+}
+
+void CompositorImpl::CreateOutputSurface(bool fallback) {
+  blink::WebGraphicsContext3D::Attributes attrs;
   attrs.shareResources = true;
   attrs.noAutomaticFlushes = true;
+  pending_swapbuffers_ = 0;
 
   DCHECK(window_);
   DCHECK(surface_id_);
 
-  scoped_refptr<ContextProviderCommandBuffer> context_provider =
-      ContextProviderCommandBuffer::Create(CreateGpuProcessViewContext(
-          attrs, surface_id_, weak_factory_.GetWeakPtr()), "BrowserCompositor");
+  scoped_refptr<ContextProviderCommandBuffer> context_provider;
+  BrowserGpuChannelHostFactory* factory =
+      BrowserGpuChannelHostFactory::instance();
+  scoped_refptr<GpuChannelHost> gpu_channel_host = factory->GetGpuChannel();
+  if (gpu_channel_host && !gpu_channel_host->IsLost()) {
+    context_provider = ContextProviderCommandBuffer::Create(
+        CreateGpuProcessViewContext(gpu_channel_host, attrs, surface_id_),
+        "BrowserCompositor");
+  }
   if (!context_provider.get()) {
     LOG(ERROR) << "Failed to create 3D context for compositor.";
-    return scoped_ptr<cc::OutputSurface>();
+    host_->SetOutputSurface(scoped_ptr<cc::OutputSurface>());
+    return;
   }
 
-  return scoped_ptr<cc::OutputSurface>(
-      new OutputSurfaceWithoutParent(context_provider));
+  host_->SetOutputSurface(
+      scoped_ptr<cc::OutputSurface>(new OutputSurfaceWithoutParent(
+          context_provider, weak_factory_.GetWeakPtr())));
+}
+
+void CompositorImpl::PopulateGpuCapabilities(
+    gpu::Capabilities gpu_capabilities) {
+  ui_resource_provider_.SetSupportsETC1NonPowerOfTwo(
+      gpu_capabilities.texture_format_etc1_npot);
 }
 
 void CompositorImpl::OnLostResources() {
   client_->DidLoseResources();
 }
 
+void CompositorImpl::ScheduleComposite() {
+  DCHECK(!needs_composite_ || WillComposite());
+  if (ignore_schedule_composite_)
+    return;
+
+  needs_composite_ = true;
+  // We currently expect layer tree invalidations at most once per frame
+  // during normal operation and therefore try to composite immediately
+  // to minimize latency.
+  PostComposite(COMPOSITE_IMMEDIATELY);
+}
+
+void CompositorImpl::ScheduleAnimation() {
+  DCHECK(!needs_composite_ || WillComposite());
+  needs_animate_ = true;
+
+  if (needs_composite_)
+    return;
+
+  TRACE_EVENT0("cc", "CompositorImpl::ScheduleAnimation");
+  needs_composite_ = true;
+  PostComposite(COMPOSITE_EVENTUALLY);
+}
+
+void CompositorImpl::DidPostSwapBuffers() {
+  TRACE_EVENT0("compositor", "CompositorImpl::DidPostSwapBuffers");
+  did_post_swapbuffers_ = true;
+}
+
 void CompositorImpl::DidCompleteSwapBuffers() {
-  client_->OnSwapBuffersCompleted();
+  TRACE_EVENT0("compositor", "CompositorImpl::DidCompleteSwapBuffers");
+  DCHECK_GT(pending_swapbuffers_, 0U);
+  if (pending_swapbuffers_-- == kMaxSwapBuffers && needs_composite_)
+    PostComposite(COMPOSITE_IMMEDIATELY);
+  client_->OnSwapBuffersCompleted(pending_swapbuffers_);
 }
 
-void CompositorImpl::ScheduleComposite() {
-  client_->ScheduleComposite();
-}
-
-scoped_refptr<cc::ContextProvider> CompositorImpl::OffscreenContextProvider() {
-  // There is no support for offscreen contexts, or compositor filters that
-  // would require them in this compositor instance. If they are needed,
-  // then implement a context provider that provides contexts from
-  // ImageTransportSurfaceAndroid.
-  return NULL;
-}
-
-void CompositorImpl::OnViewContextSwapBuffersPosted() {
-  TRACE_EVENT0("compositor", "CompositorImpl::OnViewContextSwapBuffersPosted");
-  client_->OnSwapBuffersPosted();
-}
-
-void CompositorImpl::OnViewContextSwapBuffersComplete() {
-  TRACE_EVENT0("compositor",
-               "CompositorImpl::OnViewContextSwapBuffersComplete");
-  client_->OnSwapBuffersCompleted();
-}
-
-void CompositorImpl::OnViewContextSwapBuffersAborted() {
-  TRACE_EVENT0("compositor", "CompositorImpl::OnViewContextSwapBuffersAborted");
-  client_->OnSwapBuffersCompleted();
-}
-
-WebKit::WebGLId CompositorImpl::BuildBasicTexture() {
-  WebKit::WebGraphicsContext3D* context =
-            ImageTransportFactoryAndroid::GetInstance()->GetContext3D();
-  if (context->isContextLost() || !context->makeContextCurrent())
-    return 0;
-  WebKit::WebGLId texture_id = context->createTexture();
-  context->bindTexture(GL_TEXTURE_2D, texture_id);
-  context->texParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-  context->texParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-  context->texParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-  context->texParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-  return texture_id;
-}
-
-WebKit::WGC3Denum CompositorImpl::GetGLFormatForBitmap(
-    gfx::JavaBitmap& bitmap) {
-  switch (bitmap.format()) {
-    case ANDROID_BITMAP_FORMAT_A_8:
-      return GL_ALPHA;
-      break;
-    case ANDROID_BITMAP_FORMAT_RGBA_4444:
-      return GL_RGBA;
-      break;
-    case ANDROID_BITMAP_FORMAT_RGBA_8888:
-      return GL_RGBA;
-      break;
-    case ANDROID_BITMAP_FORMAT_RGB_565:
-    default:
-      return GL_RGB;
-  }
+void CompositorImpl::DidAbortSwapBuffers() {
+  TRACE_EVENT0("compositor", "CompositorImpl::DidAbortSwapBuffers");
+  // This really gets called only once from
+  // SingleThreadProxy::DidLoseOutputSurfaceOnImplThread() when the
+  // context was lost.
+  ScheduleComposite();
+  client_->OnSwapBuffersCompleted(0);
+}
+
+void CompositorImpl::DidCommit() {
+  root_window_->OnCompositingDidCommit();
+}
+
+void CompositorImpl::AttachLayerForReadback(scoped_refptr<cc::Layer> layer) {
+  root_layer_->AddChild(layer);
+}
+
+void CompositorImpl::RequestCopyOfOutputOnRootLayer(
+    scoped_ptr<cc::CopyOutputRequest> request) {
+  root_layer_->RequestCopyOfOutput(request.Pass());
 }
 
-WebKit::WGC3Denum CompositorImpl::GetGLTypeForBitmap(gfx::JavaBitmap& bitmap) {
-  switch (bitmap.format()) {
-    case ANDROID_BITMAP_FORMAT_A_8:
-      return GL_UNSIGNED_BYTE;
-      break;
-    case ANDROID_BITMAP_FORMAT_RGBA_4444:
-      return GL_UNSIGNED_SHORT_4_4_4_4;
-      break;
-    case ANDROID_BITMAP_FORMAT_RGBA_8888:
-      return GL_UNSIGNED_BYTE;
-      break;
-    case ANDROID_BITMAP_FORMAT_RGB_565:
-    default:
-      return GL_UNSIGNED_SHORT_5_6_5;
+void CompositorImpl::OnVSync(base::TimeTicks frame_time,
+                             base::TimeDelta vsync_period) {
+  vsync_period_ = vsync_period;
+  last_vsync_ = frame_time;
+
+  if (WillCompositeThisFrame()) {
+    // We somehow missed the last vsync interval, so reschedule for deadline.
+    // We cannot schedule immediately, or will get us out-of-phase with new
+    // renderer frames.
+    CancelComposite();
+    composite_on_vsync_trigger_ = COMPOSITE_EVENTUALLY;
+  } else {
+    current_composite_task_.reset();
   }
+
+  DCHECK(!DidCompositeThisFrame() && !WillCompositeThisFrame());
+  if (composite_on_vsync_trigger_ != DO_NOT_COMPOSITE) {
+    CompositingTrigger trigger = composite_on_vsync_trigger_;
+    composite_on_vsync_trigger_ = DO_NOT_COMPOSITE;
+    PostComposite(trigger);
+  }
+}
+
+void CompositorImpl::SetNeedsAnimate() {
+  if (!host_)
+    return;
+
+  host_->SetNeedsAnimate();
 }
 
-} // namespace content
+}  // namespace content