OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "sky/compositor/layer_host.h" | 5 #include "sky/compositor/layer_host.h" |
6 | 6 |
7 #include "base/debug/trace_event.h" | 7 #include "base/debug/trace_event.h" |
8 #include "base/message_loop/message_loop.h" | 8 #include "base/message_loop/message_loop.h" |
9 #include "mojo/converters/geometry/geometry_type_converters.h" | 9 #include "mojo/converters/geometry/geometry_type_converters.h" |
10 #include "mojo/gpu/gl_context.h" | 10 #include "mojo/gpu/gl_context.h" |
11 #include "mojo/services/public/cpp/surfaces/surfaces_utils.h" | 11 #include "mojo/services/public/cpp/surfaces/surfaces_utils.h" |
12 #include "mojo/skia/ganesh_context.h" | 12 #include "mojo/skia/ganesh_context.h" |
13 #include "sky/compositor/layer.h" | 13 #include "sky/compositor/layer.h" |
14 | 14 |
15 namespace sky { | 15 namespace sky { |
16 | 16 |
17 LayerHost::LayerHost(LayerHostClient* client) | 17 LayerHost::LayerHost(LayerHostClient* client) |
18 : client_(client), | 18 : client_(client), |
19 state_(kIdle), | 19 state_(kWaitingForSurfaceService), |
| 20 frame_requested_(false), |
20 surface_holder_(this, client->GetShell()), | 21 surface_holder_(this, client->GetShell()), |
21 gl_context_(mojo::GLContext::Create(client->GetShell())), | 22 gl_context_(mojo::GLContext::Create(client->GetShell())), |
22 ganesh_context_(gl_context_), | 23 ganesh_context_(gl_context_), |
23 resource_manager_(gl_context_), | 24 resource_manager_(gl_context_), |
24 scheduler_(this, base::MessageLoop::current()->task_runner()) { | 25 weak_factory_(this) { |
25 scheduler_.UpdateVSync( | |
26 TimeInterval(base::TimeTicks(), base::TimeDelta::FromSecondsD(1.0 / 60))); | |
27 } | 26 } |
28 | 27 |
29 LayerHost::~LayerHost() { | 28 LayerHost::~LayerHost() { |
30 } | 29 } |
31 | 30 |
32 void LayerHost::SetNeedsAnimate() { | 31 void LayerHost::SetNeedsAnimate() { |
33 scheduler_.SetNeedsFrame(); | 32 if (frame_requested_) |
34 state_ = kWaitingForBeginFrame; | 33 return; |
| 34 frame_requested_ = true; |
| 35 if (state_ == kReadyForFrame) |
| 36 BeginFrameSoon(); |
35 } | 37 } |
36 | 38 |
37 void LayerHost::SetRootLayer(scoped_refptr<Layer> layer) { | 39 void LayerHost::SetRootLayer(scoped_refptr<Layer> layer) { |
38 DCHECK(!root_layer_.get()); | 40 DCHECK(!root_layer_.get()); |
39 root_layer_ = layer; | 41 root_layer_ = layer; |
40 root_layer_->set_host(this); | 42 root_layer_->set_host(this); |
41 } | 43 } |
42 | 44 |
| 45 void LayerHost::OnSurfaceConnectionCreated() { |
| 46 DCHECK_EQ(state_, kWaitingForSurfaceService); |
| 47 state_ = kReadyForFrame; |
| 48 if (frame_requested_) |
| 49 BeginFrameSoon(); |
| 50 } |
| 51 |
43 void LayerHost::OnSurfaceIdAvailable(mojo::SurfaceIdPtr surface_id) { | 52 void LayerHost::OnSurfaceIdAvailable(mojo::SurfaceIdPtr surface_id) { |
44 client_->OnSurfaceIdAvailable(surface_id.Pass()); | 53 client_->OnSurfaceIdAvailable(surface_id.Pass()); |
45 | |
46 if (state_ == kWaitingForSurfaceToUploadFrame) | |
47 Upload(root_layer_.get()); | |
48 } | 54 } |
49 | 55 |
50 void LayerHost::ReturnResources( | 56 void LayerHost::ReturnResources( |
51 mojo::Array<mojo::ReturnedResourcePtr> resources) { | 57 mojo::Array<mojo::ReturnedResourcePtr> resources) { |
52 resource_manager_.ReturnResources(resources.Pass()); | 58 resource_manager_.ReturnResources(resources.Pass()); |
53 } | 59 } |
54 | 60 |
55 void LayerHost::BeginFrame(base::TimeTicks frame_time, | 61 void LayerHost::BeginFrameSoon() { |
56 base::TimeTicks deadline) { | 62 base::MessageLoop::current()->PostTask( |
| 63 FROM_HERE, |
| 64 base::Bind(&LayerHost::BeginFrame, weak_factory_.GetWeakPtr())); |
| 65 } |
57 | 66 |
| 67 void LayerHost::BeginFrame() { |
58 TRACE_EVENT0("sky", "LayerHost::BeginFrame"); | 68 TRACE_EVENT0("sky", "LayerHost::BeginFrame"); |
59 | 69 |
60 DCHECK_EQ(state_, kWaitingForBeginFrame); | 70 DCHECK(frame_requested_); |
61 state_ = kProducingFrame; | 71 frame_requested_ = false; |
62 client_->BeginFrame(frame_time); | 72 |
| 73 DCHECK_EQ(state_, kReadyForFrame); |
| 74 state_ = kWaitingForFrameAcknowldgement; |
| 75 |
| 76 client_->BeginFrame(base::TimeTicks::Now()); |
63 | 77 |
64 { | 78 { |
65 mojo::GaneshContext::Scope scope(&ganesh_context_); | 79 mojo::GaneshContext::Scope scope(&ganesh_context_); |
66 ganesh_context_.gr()->resetContext(); | 80 ganesh_context_.gr()->resetContext(); |
67 root_layer_->Display(); | 81 root_layer_->Display(); |
68 } | 82 } |
69 | 83 |
70 Upload(root_layer_.get()); | 84 Upload(root_layer_.get()); |
71 | |
72 if (state_ == kProducingFrame) | |
73 state_ = kIdle; | |
74 } | 85 } |
75 | 86 |
76 void LayerHost::Upload(Layer* layer) { | 87 void LayerHost::Upload(Layer* layer) { |
77 TRACE_EVENT0("sky", "LayerHost::Upload"); | 88 TRACE_EVENT0("sky", "LayerHost::Upload"); |
78 | 89 |
79 if (!surface_holder_.IsReadyForFrame()) { | |
80 if (state_ == kProducingFrame) { | |
81 // Currently we use a timer to drive the BeginFrame cycle, which means we | |
82 // can produce frames before the surfaces service is ready to receive | |
83 // frames from us. In that situation, we wait for surfaces before | |
84 // uploading the frame. The upload will actually happen when the surface | |
85 // id is available (i.e., in OnSurfaceIdAvailable). If SetNeedsAnimate is | |
86 // called before then, we'll go back into the kWaitingForBeginFrame state | |
87 // and defer to the timer again. | |
88 // | |
89 // We can avoid this complexity if we use feedback from the surfaces | |
90 // service to drive the BeginFrame cycle. In that approach, we wouldn't | |
91 // get here before we've attached to a surface. | |
92 state_ = kWaitingForSurfaceToUploadFrame; | |
93 } | |
94 return; | |
95 } | |
96 | |
97 gfx::Size size = layer->size(); | 90 gfx::Size size = layer->size(); |
98 surface_holder_.SetSize(size); | 91 surface_holder_.SetSize(size); |
99 | 92 |
100 mojo::FramePtr frame = mojo::Frame::New(); | 93 mojo::FramePtr frame = mojo::Frame::New(); |
101 frame->resources.resize(0u); | 94 frame->resources.resize(0u); |
102 | 95 |
103 mojo::Rect bounds; | 96 mojo::Rect bounds; |
104 bounds.width = size.width(); | 97 bounds.width = size.width(); |
105 bounds.height = size.height(); | 98 bounds.height = size.height(); |
106 mojo::PassPtr pass = mojo::CreateDefaultPass(1, bounds); | 99 mojo::PassPtr pass = mojo::CreateDefaultPass(1, bounds); |
(...skipping 27 matching lines...) Expand all Loading... |
134 texture_state->background_color->rgba = 0; | 127 texture_state->background_color->rgba = 0; |
135 for (int i = 0; i < 4; ++i) | 128 for (int i = 0; i < 4; ++i) |
136 texture_state->vertex_opacity.push_back(1.f); | 129 texture_state->vertex_opacity.push_back(1.f); |
137 texture_state->flipped = false; | 130 texture_state->flipped = false; |
138 | 131 |
139 frame->resources.push_back(resource.Pass()); | 132 frame->resources.push_back(resource.Pass()); |
140 quad->texture_quad_state = texture_state.Pass(); | 133 quad->texture_quad_state = texture_state.Pass(); |
141 pass->quads.push_back(quad.Pass()); | 134 pass->quads.push_back(quad.Pass()); |
142 | 135 |
143 frame->passes.push_back(pass.Pass()); | 136 frame->passes.push_back(pass.Pass()); |
144 surface_holder_.SubmitFrame(frame.Pass()); | 137 surface_holder_.SubmitFrame( |
| 138 frame.Pass(), |
| 139 base::Bind(&LayerHost::DidCompleteFrame, weak_factory_.GetWeakPtr())); |
| 140 } |
| 141 |
| 142 void LayerHost::DidCompleteFrame() { |
| 143 DCHECK_EQ(state_, kWaitingForFrameAcknowldgement); |
| 144 state_ = kReadyForFrame; |
| 145 if (frame_requested_) |
| 146 BeginFrame(); |
145 } | 147 } |
146 | 148 |
147 } // namespace sky | 149 } // namespace sky |
OLD | NEW |