Skip to content

Commit 24f00a7

Browse files
committed
Revert "Revert skiping illegal render in Dart (flutter#49473)"
This reverts commit 4325486.
1 parent 6810c9a commit 24f00a7

File tree

5 files changed

+48
-66
lines changed

5 files changed

+48
-66
lines changed

lib/ui/platform_dispatcher.dart

Lines changed: 19 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -308,9 +308,8 @@ class PlatformDispatcher {
308308
_invoke(onMetricsChanged, _onMetricsChangedZone);
309309
}
310310

311-
// A debug-only variable that stores the [FlutterView]s for which
312-
// [FlutterView.render] has already been called during the current
313-
// [onBeginFrame]/[onDrawFrame] callback sequence.
311+
// The [FlutterView]s for which [FlutterView.render] has already been called
312+
// during the current [onBeginFrame]/[onDrawFrame] callback sequence.
314313
//
315314
// It is null outside the scope of those callbacks indicating that calls to
316315
// [FlutterView.render] must be ignored. Furthermore, if a given [FlutterView]
@@ -320,16 +319,9 @@ class PlatformDispatcher {
320319
// Between [onBeginFrame] and [onDrawFrame] the properties value is
321320
// temporarily stored in `_renderedViewsBetweenCallbacks` so that it survives
322321
// the gap between the two callbacks.
323-
//
324-
// In release build, this variable is null, and therefore the calling rule is
325-
// not enforced. This is because the check might hurt cold startup delay;
326-
// see https://github.com/flutter/engine/pull/46919.
327-
Set<FlutterView>? _debugRenderedViews;
328-
// A debug-only variable that temporarily stores the `_renderedViews` value
329-
// between `_beginFrame` and `_drawFrame`.
330-
//
331-
// In release build, this variable is null.
332-
Set<FlutterView>? _debugRenderedViewsBetweenCallbacks;
322+
Set<FlutterView>? _renderedViews;
323+
// The `_renderedViews` value between `_beginFrame` and `_drawFrame`.
324+
Set<FlutterView>? _renderedViewsBetweenCallbacks;
333325

334326
/// A callback invoked when any view begins a frame.
335327
///
@@ -351,26 +343,20 @@ class PlatformDispatcher {
351343

352344
// Called from the engine, via hooks.dart
353345
void _beginFrame(int microseconds) {
354-
assert(_debugRenderedViews == null);
355-
assert(_debugRenderedViewsBetweenCallbacks == null);
356-
assert(() {
357-
_debugRenderedViews = <FlutterView>{};
358-
return true;
359-
}());
346+
assert(_renderedViews == null);
347+
assert(_renderedViewsBetweenCallbacks == null);
348+
_renderedViews = <FlutterView>{};
360349

361350
_invoke1<Duration>(
362351
onBeginFrame,
363352
_onBeginFrameZone,
364353
Duration(microseconds: microseconds),
365354
);
366355

367-
assert(_debugRenderedViews != null);
368-
assert(_debugRenderedViewsBetweenCallbacks == null);
369-
assert(() {
370-
_debugRenderedViewsBetweenCallbacks = _debugRenderedViews;
371-
_debugRenderedViews = null;
372-
return true;
373-
}());
356+
assert(_renderedViews != null);
357+
assert(_renderedViewsBetweenCallbacks == null);
358+
_renderedViewsBetweenCallbacks = _renderedViews;
359+
_renderedViews = null;
374360
}
375361

376362
/// A callback that is invoked for each frame after [onBeginFrame] has
@@ -388,22 +374,16 @@ class PlatformDispatcher {
388374

389375
// Called from the engine, via hooks.dart
390376
void _drawFrame() {
391-
assert(_debugRenderedViews == null);
392-
assert(_debugRenderedViewsBetweenCallbacks != null);
393-
assert(() {
394-
_debugRenderedViews = _debugRenderedViewsBetweenCallbacks;
395-
_debugRenderedViewsBetweenCallbacks = null;
396-
return true;
397-
}());
377+
assert(_renderedViews == null);
378+
assert(_renderedViewsBetweenCallbacks != null);
379+
_renderedViews = _renderedViewsBetweenCallbacks;
380+
_renderedViewsBetweenCallbacks = null;
398381

399382
_invoke(onDrawFrame, _onDrawFrameZone);
400383

401-
assert(_debugRenderedViews != null);
402-
assert(_debugRenderedViewsBetweenCallbacks == null);
403-
assert(() {
404-
_debugRenderedViews = null;
405-
return true;
406-
}());
384+
assert(_renderedViews != null);
385+
assert(_renderedViewsBetweenCallbacks == null);
386+
_renderedViews = null;
407387
}
408388

409389
/// A callback that is invoked when pointer data is available.

lib/ui/window.dart

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -373,14 +373,8 @@ class FlutterView {
373373
/// painting.
374374
void render(Scene scene, {Size? size}) {
375375
// Duplicated calls or calls outside of onBeginFrame/onDrawFrame (indicated
376-
// by _debugRenderedViews being null) are ignored. See _debugRenderedViews.
377-
// TODO(dkwingsmt): We should change this skip into an assertion.
378-
// https://github.com/flutter/flutter/issues/137073
379-
bool validRender = true;
380-
assert(() {
381-
validRender = platformDispatcher._debugRenderedViews?.add(this) ?? false;
382-
return true;
383-
}());
376+
// by _renderedViews being null) are ignored. See _renderedViews.
377+
final bool validRender = platformDispatcher._renderedViews?.add(this) ?? false;
384378
if (validRender) {
385379
_render(scene as _NativeScene, size?.width ?? physicalSize.width, size?.height ?? physicalSize.height);
386380
}

shell/common/animator.cc

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -143,15 +143,12 @@ void Animator::BeginFrame(
143143

144144
void Animator::Render(std::unique_ptr<flutter::LayerTree> layer_tree,
145145
float device_pixel_ratio) {
146-
has_rendered_ = true;
147-
148-
if (!frame_timings_recorder_) {
149-
// Framework can directly call render with a built scene.
150-
frame_timings_recorder_ = std::make_unique<FrameTimingsRecorder>();
151-
const fml::TimePoint placeholder_time = fml::TimePoint::Now();
152-
frame_timings_recorder_->RecordVsync(placeholder_time, placeholder_time);
153-
frame_timings_recorder_->RecordBuildStart(placeholder_time);
146+
// Animator::Render should be called after BeginFrame, which is indicated by
147+
// frame_timings_recorder_ being non-null. Otherwise, this call is ignored.
148+
if (frame_timings_recorder_ == nullptr) {
149+
return;
154150
}
151+
has_rendered_ = true;
155152

156153
TRACE_EVENT_WITH_FRAME_NUMBER(frame_timings_recorder_, "flutter",
157154
"Animator::Render", /*flow_id_count=*/0,

shell/common/animator.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ class Animator final {
5858
///
5959
/// This method must be called during a vsync callback, or
6060
/// technically, between Animator::BeginFrame and Animator::EndFrame
61-
/// (both private methods). Otherwise, this call will be ignored.
61+
/// (both private methods). Otherwise, an assertion will be
62+
/// triggered.
6263
///
6364
void Render(std::unique_ptr<flutter::LayerTree> layer_tree,
6465
float device_pixel_ratio);

shell/common/animator_unittests.cc

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -158,20 +158,30 @@ TEST_F(ShellTest, AnimatorDoesNotNotifyIdleBeforeRender) {
158158
latch.Wait();
159159
ASSERT_FALSE(delegate.notify_idle_called_);
160160

161+
fml::AutoResetWaitableEvent render_latch;
161162
// Validate it has not notified idle and try to render.
162163
task_runners.GetUITaskRunner()->PostDelayedTask(
163164
[&] {
164165
ASSERT_FALSE(delegate.notify_idle_called_);
165-
auto layer_tree = std::make_unique<LayerTree>(LayerTree::Config(),
166-
SkISize::Make(600, 800));
167-
animator->Render(std::move(layer_tree), 1.0);
166+
EXPECT_CALL(delegate, OnAnimatorBeginFrame).WillOnce([&] {
167+
auto layer_tree = std::make_unique<LayerTree>(
168+
LayerTree::Config(), SkISize::Make(600, 800));
169+
animator->Render(std::move(layer_tree), 1.0);
170+
render_latch.Signal();
171+
});
172+
// Request a frame that builds a layer tree and renders a frame.
173+
// When the frame is rendered, render_latch will be signaled.
174+
animator->RequestFrame(true);
168175
task_runners.GetPlatformTaskRunner()->PostTask(flush_vsync_task);
169176
},
170177
// See kNotifyIdleTaskWaitTime in animator.cc.
171178
fml::TimeDelta::FromMilliseconds(60));
172179
latch.Wait();
180+
render_latch.Wait();
173181

174-
// Still hasn't notified idle because there has been no frame request.
182+
// A frame has been rendered, and the next frame request will notify idle.
183+
// But at the moment there isn't another frame request, therefore it still
184+
// hasn't notified idle.
175185
task_runners.GetUITaskRunner()->PostTask([&] {
176186
ASSERT_FALSE(delegate.notify_idle_called_);
177187
// False to avoid getting cals to BeginFrame that will request more frames
@@ -239,16 +249,16 @@ TEST_F(ShellTest, AnimatorDoesNotNotifyDelegateIfPipelineIsNotEmpty) {
239249

240250
for (int i = 0; i < 2; i++) {
241251
task_runners.GetUITaskRunner()->PostTask([&] {
252+
EXPECT_CALL(delegate, OnAnimatorBeginFrame).WillOnce([&] {
253+
auto layer_tree = std::make_unique<LayerTree>(LayerTree::Config(),
254+
SkISize::Make(600, 800));
255+
animator->Render(std::move(layer_tree), 1.0);
256+
begin_frame_latch.Signal();
257+
});
242258
animator->RequestFrame();
243259
task_runners.GetPlatformTaskRunner()->PostTask(flush_vsync_task);
244260
});
245261
begin_frame_latch.Wait();
246-
247-
PostTaskSync(task_runners.GetUITaskRunner(), [&] {
248-
auto layer_tree = std::make_unique<LayerTree>(LayerTree::Config(),
249-
SkISize::Make(600, 800));
250-
animator->Render(std::move(layer_tree), 1.0);
251-
});
252262
}
253263

254264
PostTaskSync(task_runners.GetUITaskRunner(), [&] { animator.reset(); });

0 commit comments

Comments
 (0)