Automatically redraw the display on resume.

- OnscreenContextProvider notifies the CommandBufferImpl when the context has
  been lost.
- This in turn causes DisplayImpl::OutputSurfaceLost() to be called, which
  results in it calling back to OnscreenContextProvider to ask it to create a
  new context when suitable.

This patch is heavily based off https://codereview.chromium.org/1116883002/ by
etiennej@chromium.org.

R=jamesr@chromium.org

Review URL: https://codereview.chromium.org/1123623003
diff --git a/services/gles2/command_buffer_impl.cc b/services/gles2/command_buffer_impl.cc
index c370068..29a772c 100644
--- a/services/gles2/command_buffer_impl.cc
+++ b/services/gles2/command_buffer_impl.cc
@@ -57,6 +57,7 @@
       driver_(driver.Pass()),
       viewport_parameter_listener_(listener.Pass()),
       binding_(this),
+      observer_(nullptr),
       weak_factory_(this) {
   driver_->set_client(make_scoped_ptr(new CommandBufferDriverClientImpl(
       weak_factory_.GetWeakPtr(), control_task_runner)));
@@ -67,6 +68,9 @@
 }
 
 CommandBufferImpl::~CommandBufferImpl() {
+  if (observer_) {
+    observer_->OnCommandBufferImplDestroyed();
+  }
   driver_task_runner_->PostTask(
       FROM_HERE, base::Bind(&DestroyDriver, base::Passed(&driver_)));
 }
diff --git a/services/gles2/command_buffer_impl.h b/services/gles2/command_buffer_impl.h
index a6bf27d..44bf85b 100644
--- a/services/gles2/command_buffer_impl.h
+++ b/services/gles2/command_buffer_impl.h
@@ -25,6 +25,11 @@
 // same thread as the native viewport.
 class CommandBufferImpl : public mojo::CommandBuffer {
  public:
+  class Observer {
+   public:
+    virtual void OnCommandBufferImplDestroyed() = 0;
+  };
+
   CommandBufferImpl(
       mojo::InterfaceRequest<CommandBuffer> request,
       mojo::ViewportParameterListenerPtr listener,
@@ -52,6 +57,8 @@
   void UpdateVSyncParameters(base::TimeTicks timebase,
                              base::TimeDelta interval);
 
+  void set_observer(Observer* observer) { observer_ = observer; }
+
  private:
   void BindToRequest(mojo::InterfaceRequest<CommandBuffer> request);
 
@@ -61,6 +68,7 @@
   mojo::CommandBufferSyncPointClientPtr sync_point_client_;
   mojo::ViewportParameterListenerPtr viewport_parameter_listener_;
   mojo::StrongBinding<CommandBuffer> binding_;
+  Observer* observer_;
 
   base::WeakPtrFactory<CommandBufferImpl> weak_factory_;
   DISALLOW_COPY_AND_ASSIGN(CommandBufferImpl);
diff --git a/services/native_viewport/onscreen_context_provider.cc b/services/native_viewport/onscreen_context_provider.cc
index c34ff86..a7ba14b 100644
--- a/services/native_viewport/onscreen_context_provider.cc
+++ b/services/native_viewport/onscreen_context_provider.cc
@@ -5,17 +5,21 @@
 #include "services/native_viewport/onscreen_context_provider.h"
 
 #include "services/gles2/command_buffer_driver.h"
-#include "services/gles2/command_buffer_impl.h"
 #include "services/gles2/gpu_state.h"
 
 namespace native_viewport {
 
 OnscreenContextProvider::OnscreenContextProvider(
     const scoped_refptr<gles2::GpuState>& state)
-    : state_(state), widget_(gfx::kNullAcceleratedWidget), binding_(this) {
+    : command_buffer_impl_(nullptr),
+      state_(state),
+      widget_(gfx::kNullAcceleratedWidget),
+      binding_(this) {
 }
 
 OnscreenContextProvider::~OnscreenContextProvider() {
+  if (command_buffer_impl_)
+    command_buffer_impl_->set_observer(nullptr);
 }
 
 void OnscreenContextProvider::Bind(
@@ -26,16 +30,26 @@
 void OnscreenContextProvider::SetAcceleratedWidget(
     gfx::AcceleratedWidget widget) {
   widget_ = widget;
-  if (widget_ != gfx::kNullAcceleratedWidget &&
-      !pending_create_callback_.is_null())
-    CreateAndReturnCommandBuffer();
+
+  if (widget_ == gfx::kNullAcceleratedWidget) {
+    if (command_buffer_impl_)
+      command_buffer_impl_->DidLoseContext();
+    return;
+  }
+
+  if (pending_create_callback_.is_null())
+    return;
+
+  CreateAndReturnCommandBuffer();
 }
 
 void OnscreenContextProvider::Create(
     mojo::ViewportParameterListenerPtr viewport_parameter_listener,
     const CreateCallback& callback) {
-  if (!pending_create_callback_.is_null())
+  if (!pending_create_callback_.is_null()) {
+    DCHECK(!command_buffer_impl_);
     pending_create_callback_.Run(nullptr);
+  }
   pending_listener_ = viewport_parameter_listener.Pass();
   pending_create_callback_ = callback;
 
@@ -43,14 +57,20 @@
     CreateAndReturnCommandBuffer();
 }
 
+void OnscreenContextProvider::OnCommandBufferImplDestroyed() {
+  DCHECK(command_buffer_impl_);
+  command_buffer_impl_ = nullptr;
+}
+
 void OnscreenContextProvider::CreateAndReturnCommandBuffer() {
   mojo::CommandBufferPtr cb;
-  new gles2::CommandBufferImpl(
+  command_buffer_impl_ = new gles2::CommandBufferImpl(
       GetProxy(&cb), pending_listener_.Pass(), state_->control_task_runner(),
       state_->sync_point_manager(),
       make_scoped_ptr(new gles2::CommandBufferDriver(
           widget_, state_->share_group(), state_->mailbox_manager(),
           state_->sync_point_manager())));
+  command_buffer_impl_->set_observer(this);
   pending_create_callback_.Run(cb.Pass());
   pending_create_callback_.reset();
 }
diff --git a/services/native_viewport/onscreen_context_provider.h b/services/native_viewport/onscreen_context_provider.h
index 04115cb..46ab1b1 100644
--- a/services/native_viewport/onscreen_context_provider.h
+++ b/services/native_viewport/onscreen_context_provider.h
@@ -8,6 +8,7 @@
 #include "base/memory/ref_counted.h"
 #include "mojo/services/gpu/public/interfaces/context_provider.mojom.h"
 #include "mojo/services/gpu/public/interfaces/viewport_parameter_listener.mojom.h"
+#include "services/gles2/command_buffer_impl.h"
 #include "ui/gfx/native_widget_types.h"
 
 namespace gles2 {
@@ -16,7 +17,8 @@
 
 namespace native_viewport {
 
-class OnscreenContextProvider : public mojo::ContextProvider {
+class OnscreenContextProvider : public mojo::ContextProvider,
+                                public gles2::CommandBufferImpl::Observer {
  public:
   explicit OnscreenContextProvider(const scoped_refptr<gles2::GpuState>& state);
   ~OnscreenContextProvider() override;
@@ -30,8 +32,12 @@
   void Create(mojo::ViewportParameterListenerPtr viewport_parameter_listener,
               const CreateCallback& callback) override;
 
+  // gles2::CommandBufferImpl::Observer implementation:
+  void OnCommandBufferImplDestroyed() override;
+
   void CreateAndReturnCommandBuffer();
 
+  gles2::CommandBufferImpl* command_buffer_impl_;
   scoped_refptr<gles2::GpuState> state_;
   gfx::AcceleratedWidget widget_;
   mojo::ViewportParameterListenerPtr pending_listener_;
diff --git a/services/surfaces/surfaces_scheduler.cc b/services/surfaces/surfaces_scheduler.cc
index b5edb05..1a23620 100644
--- a/services/surfaces/surfaces_scheduler.cc
+++ b/services/surfaces/surfaces_scheduler.cc
@@ -37,6 +37,10 @@
 void SurfacesScheduler::AddDisplay(cc::Display* display) {
   DCHECK(displays_.find(display) == displays_.end());
   displays_.insert(display);
+
+  // A draw might be necessary (e.g., this display might be getting added on
+  // resumption from backgrounding).
+  SetNeedsDraw();
 }
 
 void SurfacesScheduler::RemoveDisplay(cc::Display* display) {