OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "cc/blimp/layer_tree_host_remote.h" | |
6 | |
7 #include "base/memory/ptr_util.h" | |
8 #include "cc/animation/animation_host.h" | |
9 #include "cc/blimp/compositor_proto_state.h" | |
10 #include "cc/blimp/compositor_proto_state_sink.h" | |
11 #include "cc/output/begin_frame_args.h" | |
12 #include "cc/output/compositor_frame_sink.h" | |
13 #include "cc/resources/ui_resource_manager.h" | |
14 #include "cc/trees/layer_tree.h" | |
15 #include "cc/trees/layer_tree_host_client.h" | |
16 #include "cc/trees/layer_tree_host_common.h" | |
17 #include "cc/trees/task_runner_provider.h" | |
18 | |
19 namespace cc { | |
20 namespace { | |
21 // We use a 16ms default frame interval because the rate at which the engine | |
22 // produces main frames doesn't matter. | |
23 base::TimeDelta kDefaultFrameInterval = base::TimeDelta::FromMilliseconds(16); | |
24 } // namespace | |
25 | |
26 LayerTreeHostRemote::InitParams::InitParams() = default; | |
27 | |
28 LayerTreeHostRemote::InitParams::~InitParams() = default; | |
29 | |
30 LayerTreeHostRemote::LayerTreeHostRemote(InitParams* params) | |
31 : LayerTreeHostRemote( | |
32 params, | |
33 base::MakeUnique<LayerTree>(std::move(params->animation_host), | |
34 this)) {} | |
35 | |
36 LayerTreeHostRemote::LayerTreeHostRemote(InitParams* params, | |
37 std::unique_ptr<LayerTree> layer_tree) | |
38 : id_(LayerTreeHost::GenerateHostId()), | |
39 source_frame_number_(0), | |
40 visible_(false), | |
41 defer_commits_(false), | |
42 main_frame_requested_from_state_sink_(false), | |
43 current_pipeline_stage_(FramePipelineStage::NONE), | |
44 max_pipeline_stage_for_current_frame_(FramePipelineStage::NONE), | |
45 requested_pipeline_stage_for_next_frame_(FramePipelineStage::NONE), | |
46 client_(params->client), | |
47 task_runner_provider_( | |
48 TaskRunnerProvider::Create(std::move(params->main_task_runner), | |
49 nullptr)), | |
50 compositor_proto_state_sink_( | |
51 std::move(params->compositor_proto_state_sink)), | |
52 settings_(*params->settings), | |
53 layer_tree_(std::move(layer_tree)), | |
54 ui_resource_manager_(base::MakeUnique<UIResourceManager>()), | |
danakj
2016/09/26 21:36:53
why is it a pointer?
Khushal
2016/09/27 01:07:49
I just did that because LTHInProcess also had a pt
| |
55 weak_factory_(this) { | |
56 DCHECK(task_runner_provider_->IsMainThread()); | |
57 DCHECK(compositor_proto_state_sink_); | |
58 DCHECK(client_); | |
59 compositor_proto_state_sink_->BindToClient(this); | |
60 } | |
61 | |
62 LayerTreeHostRemote::~LayerTreeHostRemote() = default; | |
63 | |
64 int LayerTreeHostRemote::GetId() const { | |
65 return id_; | |
66 } | |
67 | |
68 int LayerTreeHostRemote::SourceFrameNumber() const { | |
69 return source_frame_number_; | |
70 } | |
71 | |
72 LayerTree* LayerTreeHostRemote::GetLayerTree() { | |
73 return layer_tree_.get(); | |
74 } | |
75 | |
76 const LayerTree* LayerTreeHostRemote::GetLayerTree() const { | |
77 return layer_tree_.get(); | |
78 } | |
79 | |
80 UIResourceManager* LayerTreeHostRemote::GetUIResourceManager() const { | |
81 // We shouldn't really need a UIResourceManager. The layers which need this | |
82 // are never used. | |
83 LOG(ERROR) << "UIResourceManager requested."; | |
danakj
2016/09/26 21:36:52
How about notreached and return null then?
Khushal
2016/09/27 01:07:48
This is used by Painted scrollbars only, which bli
danakj
2016/09/27 20:32:43
My response would be "let's find out then" but I i
Khushal
2016/09/27 23:46:56
Okay, so we have turned turn off the use of Painte
| |
84 return ui_resource_manager_.get(); | |
85 } | |
86 | |
87 TaskRunnerProvider* LayerTreeHostRemote::GetTaskRunnerProvider() const { | |
88 return task_runner_provider_.get(); | |
89 } | |
90 | |
91 const LayerTreeSettings& LayerTreeHostRemote::GetSettings() const { | |
92 return settings_; | |
93 } | |
94 | |
95 void LayerTreeHostRemote::SetSurfaceClientId(uint32_t client_id) { | |
96 // We don't need to care about SurfaceLayers. The Surfaces system is | |
danakj
2016/09/26 21:36:52
Can we NOTREACHED?
Khushal
2016/09/27 01:07:49
The renderer will always call this still, even if
| |
97 // relevant on the client only. | |
98 } | |
99 | |
100 void LayerTreeHostRemote::SetLayerTreeMutator( | |
101 std::unique_ptr<LayerTreeMutator> mutator) { | |
102 // Compositor-worker not supported. | |
danakj
2016/09/26 21:36:52
Can we NOTREACHED?
Khushal
2016/09/27 01:07:49
I think this is all setup code which will still ru
danakj
2016/09/27 20:32:43
Perhaps we should be turning the setup code off if
Khushal
2016/09/27 23:46:56
Sure, we can do it in blink also. For all the feat
| |
103 } | |
104 | |
105 void LayerTreeHostRemote::QueueSwapPromise( | |
106 std::unique_ptr<SwapPromise> swap_promise) { | |
107 swap_promise_manager_.QueueSwapPromise(std::move(swap_promise)); | |
108 } | |
109 | |
110 SwapPromiseManager* LayerTreeHostRemote::GetSwapPromiseManager() { | |
111 return &swap_promise_manager_; | |
112 } | |
113 | |
114 void LayerTreeHostRemote::SetHasGpuRasterizationTrigger(bool has_trigger) { | |
115 // TODO(khushalsagar) : Take care of Gpu raster. | |
danakj
2016/09/26 21:36:52
Can you point at a bug?
Khushal
2016/09/27 01:07:49
Done.
| |
116 } | |
117 | |
118 void LayerTreeHostRemote::SetVisible(bool visible) { | |
119 // The visibility is controlled on the client. The value here should always be | |
120 // true and changes only during page transitions. | |
danakj
2016/09/26 21:36:52
What do you mean by it should always be true? Call
Khushal
2016/09/27 01:07:49
I was just adding this comment to point out why we
| |
121 visible_ = visible; | |
122 } | |
123 | |
124 bool LayerTreeHostRemote::IsVisible() const { | |
125 return visible_; | |
126 } | |
127 | |
128 void LayerTreeHostRemote::SetCompositorFrameSink( | |
129 std::unique_ptr<CompositorFrameSink> compositor_frame_sink) { | |
130 NOTREACHED() << "We never ask the client for a CompositorFrameSink"; | |
danakj
2016/09/26 21:36:53
"We" is a bit ambiguous here. "The LayerTreeHostCl
Khushal
2016/09/27 01:07:49
Done.
| |
131 } | |
132 | |
133 std::unique_ptr<CompositorFrameSink> | |
134 LayerTreeHostRemote::ReleaseCompositorFrameSink() { | |
135 // Since we never have a CompositorFrameSink, this is always a no-op. | |
danakj
2016/09/26 21:36:52
Can we NOTREACHED?
ps anything that is NOTREACHED
Khushal
2016/09/27 01:07:49
Well, the API says can be called safely anytime, s
danakj
2016/09/27 20:32:43
I thought this is only used by browser compositors
Khushal
2016/09/27 23:46:56
Its not there right now but I don't think its wron
| |
136 return nullptr; | |
137 } | |
138 | |
139 void LayerTreeHostRemote::SetNeedsAnimate() { | |
140 MainFrameRequested(FramePipelineStage::ANIMATE); | |
141 } | |
142 | |
143 void LayerTreeHostRemote::SetNeedsUpdateLayers() { | |
144 MainFrameRequested(FramePipelineStage::UPDATE_LAYERS); | |
145 } | |
146 | |
147 void LayerTreeHostRemote::SetNeedsCommit() { | |
148 MainFrameRequested(FramePipelineStage::COMMIT); | |
149 } | |
150 | |
151 bool LayerTreeHostRemote::BeginMainFrameRequested() const { | |
152 return requested_pipeline_stage_for_next_frame_ != FramePipelineStage::NONE; | |
153 } | |
154 | |
155 bool LayerTreeHostRemote::CommitRequested() const { | |
156 return requested_pipeline_stage_for_next_frame_ == FramePipelineStage::COMMIT; | |
157 } | |
158 | |
159 void LayerTreeHostRemote::SetDeferCommits(bool defer_commits) { | |
160 defer_commits_ = defer_commits; | |
161 ScheduleMainFrameIfNecessary(); | |
162 } | |
163 | |
164 void LayerTreeHostRemote::LayoutAndUpdateLayers() { | |
165 NOTREACHED() << "Only supported in single-threaded mode"; | |
danakj
2016/09/26 21:36:52
".. and this class does not support single-thread
Khushal
2016/09/27 01:07:49
Done.
| |
166 } | |
167 | |
168 void LayerTreeHostRemote::Composite(base::TimeTicks frame_begin_time) { | |
169 NOTREACHED() << "Only supported in single-threaded mode"; | |
danakj
2016/09/26 21:36:52
ditto
Khushal
2016/09/27 01:07:49
Done.
| |
170 } | |
171 | |
172 void LayerTreeHostRemote::SetNeedsRedraw() { | |
173 // The engine shouldn't need to care about draws. CompositorFrames are never | |
danakj
2016/09/26 21:36:53
I don't know about this. This causes the composito
Khushal
2016/09/27 01:07:49
Its redundant in the blimp case. The RenderWidget
danakj
2016/09/27 20:32:43
Ok actually it looks like browser compositors (ui:
Khushal
2016/09/27 23:46:56
I would be happier to keep consistency with the th
danakj
2016/09/28 00:32:50
Leaving it empty feels like a landmine to me, I'd
Khushal
2016/09/28 19:47:16
Done. I'll remove it from the threaded one as well
| |
174 // used here. | |
175 } | |
176 | |
177 void LayerTreeHostRemote::SetNeedsRedrawRect(const gfx::Rect& damage_rect) { | |
178 // The engine shouldn't need to care about draws. CompositorFrames are never | |
danakj
2016/09/26 21:36:52
Same.
danakj
2016/09/27 20:32:43
However RenderWidget calls this when it wants a re
Khushal
2016/09/27 23:46:56
Ah, good point. Thanks for pointing that case out.
danakj
2016/09/28 00:32:50
It sounds sketchy in that it's likely to interfere
Khushal
2016/09/28 19:47:16
In this case rather than the client, its elements
| |
179 // used here. | |
180 } | |
181 | |
182 void LayerTreeHostRemote::SetNextCommitForcesRedraw() { | |
183 // The engine shouldn't need to care about draws. CompositorFrames are never | |
danakj
2016/09/26 21:36:53
This is for testing, to ensure that it completes a
Khushal
2016/09/27 01:07:48
Still no need to send anything to the client thoug
danakj
2016/09/27 20:32:43
I guess it depends if you're running a pixel test.
Khushal
2016/09/27 23:46:56
For pixel tests my plan was to have an implementat
danakj
2016/09/28 00:32:50
I'm thinking more like gpu pixel tests: https://ww
Khushal
2016/09/28 19:47:16
Ah, okay. Can you point me to where this is done?
danakj
2016/09/29 23:59:35
Yes it's the screenshots thing. It's also interest
Khushal
2016/09/30 02:11:18
There is a super-basic complete end-to-end integra
| |
184 // used here. | |
185 } | |
186 | |
187 void LayerTreeHostRemote::NotifyInputThrottledUntilCommit() { | |
188 // We don't throttle commits right now so this is not relevant. | |
danakj
2016/09/26 21:36:52
NOTREACHED?
Khushal
2016/09/27 01:07:50
NOTIMPLEMENTED is better I think. The engine will
danakj
2016/09/27 20:32:43
OK I'm not actually sure how this will interact wi
Khushal
2016/09/27 23:46:56
So this was when I had looked at the code a while
danakj
2016/09/28 00:32:50
OK Cool that all sounds good, can you put this in
Khushal
2016/09/28 19:47:16
Done. Didn't add where on the client because that'
| |
189 } | |
190 | |
191 void LayerTreeHostRemote::UpdateTopControlsState(TopControlsState constraints, | |
192 TopControlsState current, | |
193 bool animate) { | |
194 NOTREACHED() << "Using TopControls animations is not supported"; | |
195 } | |
196 | |
197 const base::WeakPtr<InputHandler>& LayerTreeHostRemote::GetInputHandler() | |
198 const { | |
199 // Input on the compositor thread is handled on the client, so this is always | |
200 // null. | |
201 return input_handler_weak_ptr_; | |
danakj
2016/09/26 21:36:53
This is kinda awk, maybe follow up to make this re
Khushal
2016/09/27 01:07:49
Sounds good. I'll clean up in the next patch.
| |
202 } | |
203 | |
204 void LayerTreeHostRemote::DidStopFlinging() { | |
205 NOTIMPLEMENTED() << "We shouldn't be sending fling gestures to the engine"; | |
206 } | |
207 | |
208 void LayerTreeHostRemote::SetDebugState( | |
209 const LayerTreeDebugState& debug_state) { | |
210 debug_state_ = debug_state; | |
danakj
2016/09/26 21:36:53
How does this get to the client? Should it not Set
Khushal
2016/09/27 01:07:49
If there is a need to see debug info, then that ca
danakj
2016/09/27 20:32:43
Ok, why store it at all then?
How does inspector
Khushal
2016/09/27 23:46:56
Because things take a const&. I looked through the
danakj
2016/09/28 00:32:50
I can see why you made a member then, but why repl
Khushal
2016/09/28 19:47:16
Good point. I made it a NOTREACHED for now. Will c
| |
211 } | |
212 | |
213 const LayerTreeDebugState& LayerTreeHostRemote::GetDebugState() const { | |
214 return debug_state_; | |
215 } | |
216 | |
217 int LayerTreeHostRemote::ScheduleMicroBenchmark( | |
218 const std::string& benchmark_name, | |
219 std::unique_ptr<base::Value> value, | |
220 const MicroBenchmark::DoneCallback& callback) { | |
221 NOTIMPLEMENTED(); | |
danakj
2016/09/26 21:36:53
Or NOTREACHED?
Khushal
2016/09/27 01:07:49
I don't think we want to say that calling this met
danakj
2016/09/27 20:32:43
My thot is that if it doesn't work to use NOTREACH
Khushal
2016/09/27 23:46:56
Okay, you're right. This one's used by Gpu benchma
| |
222 return 0; | |
223 } | |
224 | |
225 bool LayerTreeHostRemote::SendMessageToMicroBenchmark( | |
226 int id, | |
227 std::unique_ptr<base::Value> value) { | |
228 NOTIMPLEMENTED(); | |
danakj
2016/09/26 21:36:53
Or NOTREACHED?
Khushal
2016/09/27 01:07:49
Same.
| |
229 return false; | |
230 } | |
231 | |
232 SurfaceSequenceGenerator* LayerTreeHostRemote::GetSurfaceSequenceGenerator() { | |
233 return &surface_sequence_generator_; | |
danakj
2016/09/26 21:36:53
This is for surfacelayer also like below. So why s
Khushal
2016/09/27 01:07:49
Yeah, it won't work. I still wasn't sure if I shou
danakj
2016/09/27 20:32:43
We shouldn't crash, the code that calls this shoul
Khushal
2016/09/27 23:46:56
Fair point. Added a TODO to turn this off in blink
| |
234 } | |
235 | |
236 void LayerTreeHostRemote::SetNextCommitWaitsForActivation() { | |
237 // This is used only by layers that need resource synchronization, i.e., | |
238 // texture and surface layers, both of which are not supported. | |
239 NOTIMPLEMENTED() << "Unsupported Layer type used"; | |
240 } | |
241 | |
242 void LayerTreeHostRemote::ResetGpuRasterizationTracking() {} | |
danakj
2016/09/26 21:36:52
TODO? Is there a bug to link to?
Khushal
2016/09/27 01:07:49
Done.
| |
243 | |
244 void LayerTreeHostRemote::MainFrameRequested( | |
245 FramePipelineStage requested_pipeline_stage) { | |
246 DCHECK_NE(FramePipelineStage::NONE, requested_pipeline_stage); | |
247 | |
248 swap_promise_manager_.NotifySwapPromiseMonitorsOfSetNeedsCommit(); | |
249 | |
250 // If we are inside a main frame update right now and the requested pipeline | |
251 // stage is higher than the pipeline stage that we are at, then we'll get to | |
252 // in this main frame update itself. Update the | |
253 // |max_pipeline_stage_for_current_frame_| to ensure we go through the | |
254 // requested pipeline stage. | |
255 if (current_pipeline_stage_ != FramePipelineStage::NONE && | |
256 requested_pipeline_stage > current_pipeline_stage_) { | |
257 max_pipeline_stage_for_current_frame_ = std::max( | |
258 max_pipeline_stage_for_current_frame_, requested_pipeline_stage); | |
259 return; | |
260 } | |
261 | |
262 // Update the pipeline stage for the next frame and schedule an update if it | |
263 // has not been scheduled already. | |
264 requested_pipeline_stage_for_next_frame_ = std::max( | |
265 requested_pipeline_stage_for_next_frame_, requested_pipeline_stage); | |
266 | |
267 ScheduleMainFrameIfNecessary(); | |
268 } | |
269 | |
270 void LayerTreeHostRemote::ScheduleMainFrameIfNecessary() { | |
271 // If the client hasn't asked for a main frame, don't schedule one. | |
272 if (requested_pipeline_stage_for_next_frame_ == FramePipelineStage::NONE) | |
273 return; | |
274 | |
275 // If the client does not want us to run main frame updates right now, don't | |
276 // schedule one. | |
277 if (defer_commits_) | |
278 return; | |
279 | |
280 // If a main frame request is already pending with the CompositorFrameSink, | |
danakj
2016/09/26 21:36:53
I don't think you mean CompositorFrameSink
Khushal
2016/09/27 01:07:49
Done.
So I was hoping that this name wouldn't cau
| |
281 // we don't need to scheduler another one. | |
282 if (main_frame_requested_from_state_sink_) | |
283 return; | |
284 | |
285 compositor_proto_state_sink_->ScheduleMainFrame(); | |
286 main_frame_requested_from_state_sink_ = true; | |
287 } | |
288 | |
289 void LayerTreeHostRemote::BeginMainFrame() { | |
290 DCHECK(main_frame_requested_from_state_sink_); | |
291 | |
292 main_frame_requested_from_state_sink_ = false; | |
293 | |
294 // The client might have suspended main frames in the meantime. Early out now, | |
295 // we'll come back here when they enable main frames again. | |
296 if (defer_commits_) | |
297 return; | |
298 | |
299 DCHECK_EQ(FramePipelineStage::NONE, current_pipeline_stage_); | |
danakj
2016/09/26 21:36:52
can you write these in the same order you'd write
Khushal
2016/09/27 01:07:48
Done. I was actually looking for comments above th
| |
300 DCHECK_EQ(FramePipelineStage::NONE, max_pipeline_stage_for_current_frame_); | |
301 DCHECK_NE(FramePipelineStage::NONE, requested_pipeline_stage_for_next_frame_); | |
302 | |
303 // Start the main frame. It should go till the requested pipeline stage. | |
304 max_pipeline_stage_for_current_frame_ = | |
305 requested_pipeline_stage_for_next_frame_; | |
306 requested_pipeline_stage_for_next_frame_ = FramePipelineStage::NONE; | |
307 | |
308 client_->WillBeginMainFrame(); | |
309 | |
310 current_pipeline_stage_ = FramePipelineStage::ANIMATE; | |
311 base::TimeTicks now = base::TimeTicks::Now(); | |
312 client_->BeginMainFrame(BeginFrameArgs::Create( | |
313 BEGINFRAME_FROM_HERE, now, now + kDefaultFrameInterval, | |
314 kDefaultFrameInterval, BeginFrameArgs::NORMAL)); | |
315 // We don't run any animations on the layer because threaded animations are | |
316 // disabled. | |
317 // TODO(khushalsagar): Revisit this when adding support for animations. | |
318 DCHECK(!layer_tree_->animation_host()->needs_push_properties()); | |
319 client_->UpdateLayerTreeHost(); | |
320 | |
321 current_pipeline_stage_ = FramePipelineStage::UPDATE_LAYERS; | |
322 LayerList layer_list; | |
323 if (max_pipeline_stage_for_current_frame_ >= | |
324 FramePipelineStage::UPDATE_LAYERS) { | |
325 // Pull updates for all layers from the client. | |
danakj
2016/09/26 21:36:53
Do you really want all layers? Is this something t
Khushal
2016/09/27 01:07:50
I'm glad you asked. So in the regular case we do h
danakj
2016/09/27 20:32:43
I think not optimizing this will make the initial
Khushal
2016/09/27 23:46:56
Thanks. Added a TODO.
| |
326 LayerTreeHostCommon::CallFunctionForEveryLayer( | |
327 layer_tree_.get(), | |
328 [&layer_list](Layer* layer) { layer_list.push_back(layer); }); | |
329 | |
330 bool content_is_suitable_for_gpu = false; | |
331 bool layers_updated = | |
332 layer_tree_->UpdateLayers(layer_list, &content_is_suitable_for_gpu); | |
333 | |
334 // If pulling layer updates resulted in any content updates, we need to go | |
335 // till the commit stage. | |
336 max_pipeline_stage_for_current_frame_ = | |
danakj
2016/09/26 21:36:52
This is a weird way to write
if (layers_updated)
Khushal
2016/09/27 01:07:49
Done.
| |
337 layers_updated ? FramePipelineStage::COMMIT | |
338 : max_pipeline_stage_for_current_frame_; | |
339 } | |
340 | |
341 current_pipeline_stage_ = FramePipelineStage::COMMIT; | |
342 client_->WillCommit(); | |
343 | |
344 if (max_pipeline_stage_for_current_frame_ < current_pipeline_stage_) { | |
345 // There is nothing to commit so break the swap promises. | |
346 swap_promise_manager_.BreakSwapPromises( | |
347 SwapPromise::DidNotSwapReason::COMMIT_NO_UPDATE); | |
348 | |
349 // For the client, the commit was successful. | |
350 MainFrameComplete(); | |
351 return; | |
352 } | |
353 | |
354 // TODO(khushalsagar): Serialize current state/reset dirty state tracking and | |
355 // return the result to the state sink instead. | |
356 std::unique_ptr<CompositorProtoState> compositor_state = | |
357 base::MakeUnique<CompositorProtoState>(); | |
358 compositor_proto_state_sink_->ProcessCompositorStateUpdate( | |
359 std::move(compositor_state)); | |
360 | |
361 MainFrameComplete(); | |
362 | |
363 // We can not wait for updates dispatched from the client about the state of | |
danakj
2016/09/26 21:36:53
Why can't you wait?
Khushal
2016/09/27 01:07:49
Because it used to end up throttling updates from
danakj
2016/09/27 20:32:43
OK Can you TODO pointing at a bug with this inform
Khushal
2016/09/27 23:46:56
Done.
| |
364 // drawing or swaps for frames sent. Since these calls can be used by the | |
365 // LayerTreeHostClient to throttle further frame updates, so dispatch them | |
366 // right after the update is processed by the state sink. | |
367 // TODO(khushalsagar): We can not really know what these callbacks end up | |
368 // being used for. Consider migrating clients to understand/cope with the fact | |
369 // that there is no actual compositing happening here. | |
370 GetMainTaskRunner()->PostTask( | |
371 FROM_HERE, base::Bind(&LayerTreeHostRemote::DispatchDrawAndSwapCallbacks, | |
372 weak_factory_.GetWeakPtr())); | |
373 } | |
374 | |
375 base::SingleThreadTaskRunner* LayerTreeHostRemote::GetMainTaskRunner() { | |
376 return task_runner_provider_->MainThreadTaskRunner(); | |
377 } | |
378 | |
379 void LayerTreeHostRemote::MainFrameComplete() { | |
380 DCHECK_EQ(current_pipeline_stage_, FramePipelineStage::COMMIT); | |
381 | |
382 current_pipeline_stage_ = FramePipelineStage::NONE; | |
383 max_pipeline_stage_for_current_frame_ = FramePipelineStage::NONE; | |
384 source_frame_number_++; | |
385 | |
386 client_->DidCommit(); | |
387 client_->DidBeginMainFrame(); | |
388 } | |
389 | |
390 void LayerTreeHostRemote::DispatchDrawAndSwapCallbacks() { | |
391 client_->DidCommitAndDrawFrame(); | |
392 client_->DidCompleteSwapBuffers(); | |
393 } | |
394 | |
395 } // namespace cc | |
OLD | NEW |