Index: blimp/client/compositor/blimp_compositor.cc |
diff --git a/blimp/client/compositor/blimp_compositor.cc b/blimp/client/compositor/blimp_compositor.cc |
index 96bad8c4fe3d524e6ddb8cc38aeb4b1040a9ae56..02cc3aca1c78099426bf310b581f012eabe980a7 100644 |
--- a/blimp/client/compositor/blimp_compositor.cc |
+++ b/blimp/client/compositor/blimp_compositor.cc |
@@ -7,6 +7,7 @@ |
#include "base/bind_helpers.h" |
#include "base/command_line.h" |
#include "base/lazy_instance.h" |
+#include "base/numerics/safe_conversions.h" |
#include "base/single_thread_task_runner.h" |
#include "base/thread_task_runner_handle.h" |
#include "base/threading/thread.h" |
@@ -17,10 +18,17 @@ |
#include "blimp/client/compositor/blimp_output_surface.h" |
#include "blimp/client/compositor/test/dummy_layer_driver.h" |
#include "blimp/common/compositor/blimp_task_graph_runner.h" |
+#include "blimp/common/proto/blimp_message.pb.h" |
+#include "blimp/common/proto/compositor.pb.h" |
+#include "blimp/common/proto/input.pb.h" |
+#include "blimp/common/proto/render_widget.pb.h" |
+#include "blimp/net/black_hole_blimp_message_processor.h" |
#include "cc/layers/layer.h" |
#include "cc/layers/layer_settings.h" |
#include "cc/output/output_surface.h" |
+#include "cc/proto/compositor_message.pb.h" |
#include "cc/trees/layer_tree_host.h" |
+#include "net/base/net_errors.h" |
#include "ui/gl/gl_surface.h" |
namespace { |
@@ -28,6 +36,11 @@ namespace { |
base::LazyInstance<blimp::BlimpTaskGraphRunner> g_task_graph_runner = |
LAZY_INSTANCE_INITIALIZER; |
+const int kDummyTabId = 0; |
+ |
+base::LazyInstance<blimp::BlackHoleBlimpMessageProcessor> |
+ g_black_hole_message_processor = LAZY_INSTANCE_INITIALIZER; |
+ |
// TODO(dtrainor): Replace this when Layer content comes from the server (see |
// crbug.com/527200 for details). |
base::LazyInstance<blimp::DummyLayerDriver> g_dummy_layer_driver = |
@@ -38,9 +51,19 @@ base::LazyInstance<blimp::DummyLayerDriver> g_dummy_layer_driver = |
namespace blimp { |
BlimpCompositor::BlimpCompositor(float dp_to_px) |
- : device_scale_factor_(dp_to_px) {} |
+ : device_scale_factor_(dp_to_px), |
+ window_(gfx::kNullAcceleratedWidget), |
+ host_should_be_visible_(false), |
+ output_surface_request_pending_(false), |
+ remote_proto_channel_receiver_(nullptr), |
+ render_widget_processor_(g_black_hole_message_processor.Pointer()) { |
+ render_widget_processor_.SetDelegate(kDummyTabId, this); |
+} |
BlimpCompositor::~BlimpCompositor() { |
+ render_widget_processor_.RemoveDelegate(kDummyTabId); |
+ SetVisible(false); |
+ |
// Destroy |host_| first, as it has a reference to the |settings_| and runs |
// tasks on |compositor_thread_|. |
host_.reset(); |
@@ -50,39 +73,27 @@ BlimpCompositor::~BlimpCompositor() { |
} |
void BlimpCompositor::SetVisible(bool visible) { |
- if (visible && !host_) { |
- if (!settings_) { |
- settings_.reset(new cc::LayerTreeSettings); |
- GenerateLayerTreeSettings(settings_.get()); |
- } |
- |
- // Create the LayerTreeHost |
- cc::LayerTreeHost::InitParams params; |
- params.client = this; |
- params.task_graph_runner = g_task_graph_runner.Pointer(); |
- params.main_task_runner = base::ThreadTaskRunnerHandle::Get(); |
- params.settings = settings_.get(); |
- |
- // TODO(dtrainor): Swap this out with the remote client proxy when |
- // implemented. |
- host_ = |
- cc::LayerTreeHost::CreateThreaded(GetCompositorTaskRunner(), ¶ms); |
- |
+ // For testing. Remove once we bind to the network layer. |
+ if (!host_) |
+ CreateLayerTreeHost(nullptr); |
+ |
+ host_should_be_visible_ = visible; |
+ if (!host_ || host_->visible() == visible) |
+ return; |
+ |
+ if (!visible) { |
nyquist
2015/11/20 08:14:59
Nit: Why the flipped conditional? I often find it
David Trainor- moved to gerrit
2015/11/25 17:56:41
Good point! Done.
|
+ // If not visible, hide the compositor and have it drop it's output surface. |
+ DCHECK(host_->visible()); |
+ host_->SetVisible(false); |
+ if (!host_->output_surface_lost()) |
+ host_->ReleaseOutputSurface(); |
+ } else { |
+ // If visible, show the compositor. If the compositor had an outstanding |
+ // output surface request, trigger the request again so we build the output |
+ // surface. |
host_->SetVisible(true); |
- host_->SetViewportSize(viewport_size_); |
- host_->SetDeviceScaleFactor(device_scale_factor_); |
- |
- // Build the root Layer. |
- scoped_refptr<cc::Layer> root(cc::Layer::Create(cc::LayerSettings())); |
- host_->SetRootLayer(root); |
- |
- // For testing, set the dummy Layer. |
- g_dummy_layer_driver.Pointer()->SetParentLayer(root); |
- |
- } else if (!visible && host_) { |
- // Release the LayerTreeHost to free all resources when the compositor is no |
- // longer visible. This will destroy the underlying compositor components. |
- host_.reset(); |
+ if (output_surface_request_pending_) |
+ RequestNewOutputSurface(); |
} |
} |
@@ -92,6 +103,31 @@ void BlimpCompositor::SetSize(const gfx::Size& size) { |
host_->SetViewportSize(viewport_size_); |
} |
+void BlimpCompositor::SetAcceleratedWidget(gfx::AcceleratedWidget widget) { |
+ if (widget == window_) |
+ return; |
+ |
+ DCHECK(window_ == gfx::kNullAcceleratedWidget); |
+ window_ = widget; |
+ |
+ // The compositor should not be visible if there is no output surface. |
+ DCHECK(!host_ || !host_->visible()); |
+ |
+ // This will properly set visibility and will build the output surface if |
+ // necessary. |
+ SetVisible(host_should_be_visible_); |
+} |
+ |
+void BlimpCompositor::ReleaseAcceleratedWidget() { |
+ if (window_ == gfx::kNullAcceleratedWidget) |
+ return; |
+ |
+ // Hide the compositor and drop the output surface if necessary. |
+ SetVisible(false); |
+ |
+ window_ = gfx::kNullAcceleratedWidget; |
+} |
+ |
void BlimpCompositor::WillBeginMainFrame() {} |
void BlimpCompositor::DidBeginMainFrame() {} |
@@ -110,14 +146,20 @@ void BlimpCompositor::ApplyViewportDeltas( |
float top_controls_delta) {} |
void BlimpCompositor::RequestNewOutputSurface() { |
- gfx::AcceleratedWidget widget = GetWindow(); |
- DCHECK(widget); |
+ output_surface_request_pending_ = true; |
+ |
+ // We might have had a request from a LayerTreeHost that was then |
+ // hidden (and hidden means we don't have a native surface). |
+ // Also make sure we only handle this once. |
+ if (!host_->visible() || window_ == gfx::kNullAcceleratedWidget) |
+ return; |
scoped_refptr<BlimpContextProvider> context_provider = |
- BlimpContextProvider::Create(widget); |
+ BlimpContextProvider::Create(window_); |
host_->SetOutputSurface( |
make_scoped_ptr(new BlimpOutputSurface(context_provider))); |
+ output_surface_request_pending_ = false; |
} |
void BlimpCompositor::DidInitializeOutputSurface() {} |
@@ -138,11 +180,78 @@ void BlimpCompositor::RecordFrameTimingEvents( |
scoped_ptr<cc::FrameTimingTracker::CompositeTimingSet> composite_events, |
scoped_ptr<cc::FrameTimingTracker::MainFrameTimingSet> main_frame_events) {} |
+void BlimpCompositor::SetProtoReceiver(ProtoReceiver* receiver) { |
+ remote_proto_channel_receiver_ = receiver; |
+} |
+ |
+void BlimpCompositor::SendCompositorProto( |
+ const cc::proto::CompositorMessage& proto) { |
+ render_widget_processor_.SendCompositorMessage(kDummyTabId, proto); |
+} |
+ |
+void BlimpCompositor::OnRenderWidgetInitialized() { |
+ // Tear down the output surface connection with the old compositor instance. |
+ SetVisible(false); |
+ |
+ // Destroy the old compositor instance. |
+ host_.reset(); |
+ |
+ // Reset other state. |
+ output_surface_request_pending_ = false; |
+ |
+ // Make sure we don't have a receiver at this point. |
+ DCHECK(!remote_proto_channel_receiver_); |
+} |
+ |
+void BlimpCompositor::OnCompositorMessageReceived( |
+ scoped_ptr<cc::proto::CompositorMessage> message) { |
+ // TODO(dtrainor, khushalsagar): Look into the CompositorMessage. If it is |
+ // initialize or shutdown, create or destroy |host_|. |
+ |
+ // We should have a receiver if we're getting compositor messages that aren't |
+ // initialize. |
+ DCHECK(remote_proto_channel_receiver_); |
+ remote_proto_channel_receiver_->OnProtoReceived(message.Pass()); |
+} |
+ |
void BlimpCompositor::GenerateLayerTreeSettings( |
cc::LayerTreeSettings* settings) { |
PopulateCommonLayerTreeSettings(settings); |
} |
+void BlimpCompositor::CreateLayerTreeHost( |
+ scoped_ptr<cc::proto::CompositorMessage> message) { |
+ if (!settings_) { |
+ settings_.reset(new cc::LayerTreeSettings); |
+ GenerateLayerTreeSettings(settings_.get()); |
+ } |
+ |
+ // Create the LayerTreeHost |
+ cc::LayerTreeHost::InitParams params; |
+ params.client = this; |
+ params.task_graph_runner = g_task_graph_runner.Pointer(); |
+ params.main_task_runner = base::ThreadTaskRunnerHandle::Get(); |
+ params.settings = settings_.get(); |
+ |
+ // TODO(dtrainor): Swap this out with the remote client proxy when |
+ // implemented. |
+ host_ = |
+ cc::LayerTreeHost::CreateThreaded(GetCompositorTaskRunner(), ¶ms); |
+ |
+ // If we're supposed to be visible and we have a valid gfx::AcceleratedWidget |
+ // make our compositor visible. |
+ if (host_should_be_visible_ && window_ != gfx::kNullAcceleratedWidget) |
+ host_->SetVisible(true); |
+ |
+ host_->SetViewportSize(viewport_size_); |
+ host_->SetDeviceScaleFactor(device_scale_factor_); |
+ |
+ // For testing, set the dummy Layer. |
+ scoped_refptr<cc::Layer> root(cc::Layer::Create(cc::LayerSettings())); |
+ host_->SetRootLayer(root); |
+ g_dummy_layer_driver.Pointer()->SetParentLayer(root); |
+} |
+ |
scoped_refptr<base::SingleThreadTaskRunner> |
BlimpCompositor::GetCompositorTaskRunner() { |
if (compositor_thread_) |