Chromium Code Reviews| 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..fa66ac4328624d061b64a6b52c7780f36b1e359f 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) { |
| + // 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() { |
|
Khushal
2015/11/19 19:28:24
We should be able to simplify this. The visibility
David Trainor- moved to gerrit
2015/11/20 17:58:53
I think this will get simplified when we split out
Khushal
2015/11/23 17:40:11
SGTM.
|
| + 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,17 +146,24 @@ void BlimpCompositor::ApplyViewportDeltas( |
| float top_controls_delta) {} |
| void BlimpCompositor::RequestNewOutputSurface() { |
| - gfx::AcceleratedWidget widget = GetWindow(); |
| - DCHECK(widget); |
| + output_surface_request_pending_ = true; |
|
Khushal
2015/11/19 19:28:24
nit: Have a method HandlePendingOutputSurfaceReque
David Trainor- moved to gerrit
2015/11/20 17:58:53
Done.
|
| + |
| + // 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))); |
| } |
| -void BlimpCompositor::DidInitializeOutputSurface() {} |
| +void BlimpCompositor::DidInitializeOutputSurface() { |
| + output_surface_request_pending_ = false; |
| +} |
| void BlimpCompositor::DidFailToInitializeOutputSurface() {} |
| @@ -138,11 +181,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_) |