Skip to content

Commit

Permalink
Revert "Add option to delay rendering the first frame (flutter#45135)" (
Browse files Browse the repository at this point in the history
flutter#45385)

This reverts commit d285b88.
  • Loading branch information
tvolkert authored Nov 22, 2019
1 parent cb35c88 commit 4c64b71
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 165 deletions.
54 changes: 2 additions & 52 deletions packages/flutter/lib/src/rendering/binding.dart
Original file line number Diff line number Diff line change
Expand Up @@ -283,53 +283,6 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture
drawFrame();
}

int _firstFrameDeferredCount = 0;
bool _firstFrameSent = false;

/// Whether frames produced by [drawFrame] are sent to the engine.
///
/// If false the framework will do all the work to produce a frame,
/// but the frame is never send to the engine to actually appear on screen.
///
/// See also:
///
/// * [deferFirstFrame], which defers when the first frame is send to the
/// engine.
bool get sendFramesToEngine => _firstFrameSent || _firstFrameDeferredCount == 0;

/// Tell the framework to not send the first frames to the engine until there
/// is a corresponding call to [allowFirstFrame].
///
/// Call this to perform asynchronous initialisation work before the first
/// frame is rendered (which takes down the splash screen). The framework
/// will still do all the work to produce frames, but those frames are never
/// send to the engine and will not appear on screen.
///
/// Calling this has no effect after the first frame has been send to the
/// engine.
void deferFirstFrame() {
assert(_firstFrameDeferredCount >= 0);
_firstFrameDeferredCount += 1;
}

/// Called after [deferFirstFrame] to tell the framework that it is ok to
/// send the first frame to the engine now.
///
/// For best performance, this method should only be called while the
/// [schedulerPhase] is [SchedulerPhase.idle].
///
/// This method may only be called once for each corresponding call
/// to [deferFirstFrame].
void allowFirstFrame() {
assert(_firstFrameDeferredCount > 0);
_firstFrameDeferredCount -= 1;
// Always schedule a warm up frame even if the deferral count is not down to
// zero yet since the removal of a deferral may uncover new deferrals that
// are lower in the widget tree.
if (!_firstFrameSent)
scheduleWarmUpFrame();
}

/// Pump the rendering pipeline to generate a frame.
///
/// This method is called by [handleDrawFrame], which itself is called
Expand Down Expand Up @@ -391,11 +344,8 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture
pipelineOwner.flushLayout();
pipelineOwner.flushCompositingBits();
pipelineOwner.flushPaint();
if (sendFramesToEngine) {
renderView.compositeFrame(); // this sends the bits to the GPU
pipelineOwner.flushSemantics(); // this also sends the semantics to the OS.
_firstFrameSent = true;
}
renderView.compositeFrame(); // this sends the bits to the GPU
pipelineOwner.flushSemantics(); // this also sends the semantics to the OS.
}

@override
Expand Down
52 changes: 26 additions & 26 deletions packages/flutter/lib/src/widgets/binding.dart
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,9 @@ mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureB
}

bool _needToReportFirstFrame = true;
int _deferFirstFrameReportCount = 0;
bool get _reportFirstFrame => _deferFirstFrameReportCount == 0;


final Completer<void> _firstFrameCompleter = Completer<void>();

Expand All @@ -597,6 +600,11 @@ mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureB

/// Whether the first frame has finished building.
///
/// Only useful in profile and debug builds; in release builds, this always
/// return false. This can be deferred using [deferFirstFrameReport] and
/// [allowFirstFrameReport]. The value is set at the end of the call to
/// [drawFrame].
///
/// This value can also be obtained over the VM service protocol as
/// `ext.flutter.didSendFirstFrameEvent`.
///
Expand All @@ -608,30 +616,27 @@ mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureB
/// Tell the framework not to report the frame it is building as a "useful"
/// first frame until there is a corresponding call to [allowFirstFrameReport].
///
/// Deprecated. Use [deferFirstFrame]/[allowFirstFrame] to delay rendering the
/// first frame.
@Deprecated(
'Use deferFirstFrame/allowFirstFrame to delay rendering the first frame. '
'This feature was deprecated after v1.12.4.'
)
/// This is used by [WidgetsApp] to avoid reporting frames that aren't useful
/// during startup as the "first frame".
void deferFirstFrameReport() {
if (!kReleaseMode) {
deferFirstFrame();
assert(_deferFirstFrameReportCount >= 0);
_deferFirstFrameReportCount += 1;
}
}

/// When called after [deferFirstFrameReport]: tell the framework to report
/// the frame it is building as a "useful" first frame.
///
/// Deprecated. Use [deferFirstFrame]/[allowFirstFrame] to delay rendering the
/// first frame.
@Deprecated(
'Use deferFirstFrame/allowFirstFrame to delay rendering the first frame. '
'This feature was deprecated after v1.12.4.'
)
/// This method may only be called once for each corresponding call
/// to [deferFirstFrameReport].
///
/// This is used by [WidgetsApp] to report when the first useful frame is
/// painted.
void allowFirstFrameReport() {
if (!kReleaseMode) {
allowFirstFrame();
assert(_deferFirstFrameReportCount >= 1);
_deferFirstFrameReportCount -= 1;
}
}

Expand Down Expand Up @@ -748,23 +753,18 @@ mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureB
return true;
}());

TimingsCallback firstFrameCallback;
if (_needToReportFirstFrame) {
if (_needToReportFirstFrame && _reportFirstFrame) {
assert(!_firstFrameCompleter.isCompleted);

TimingsCallback firstFrameCallback;
firstFrameCallback = (List<FrameTiming> timings) {
assert(sendFramesToEngine);
if (!kReleaseMode) {
developer.Timeline.instantSync('Rasterized first useful frame');
developer.postEvent('Flutter.FirstFrame', <String, dynamic>{});
}
SchedulerBinding.instance.removeTimingsCallback(firstFrameCallback);
firstFrameCallback = null;
_firstFrameCompleter.complete();
};
// Callback is only invoked when [Window.render] is called. When
// [sendFramesToEngine] is set to false during the frame, it will not
// be called and we need to remove the callback (see below).
SchedulerBinding.instance.addTimingsCallback(firstFrameCallback);
}

Expand All @@ -780,14 +780,11 @@ mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureB
}());
}
if (!kReleaseMode) {
if (_needToReportFirstFrame && sendFramesToEngine) {
if (_needToReportFirstFrame && _reportFirstFrame) {
developer.Timeline.instantSync('Widgets built first useful frame');
}
}
_needToReportFirstFrame = false;
if (firstFrameCallback != null && !sendFramesToEngine) {
SchedulerBinding.instance.removeTimingsCallback(firstFrameCallback);
}
}

/// The [Element] that is at the root of the hierarchy (and which wraps the
Expand Down Expand Up @@ -835,9 +832,12 @@ mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureB
return true;
}());

deferFirstFrameReport();
if (renderViewElement != null)
buildOwner.reassemble(renderViewElement);
return super.performReassemble();
return super.performReassemble().then((void value) {
allowFirstFrameReport();
});
}
}

Expand Down
5 changes: 2 additions & 3 deletions packages/flutter/lib/src/widgets/localizations.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import 'dart:async';
import 'dart:ui' show Locale;

import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';

import 'basic.dart';
import 'binding.dart';
Expand Down Expand Up @@ -520,9 +519,9 @@ class _LocalizationsState extends State<Localizations> {
// have finished loading. Until then the old locale will continue to be used.
// - If we're running at app startup time then defer reporting the first
// "useful" frame until after the async load has completed.
RendererBinding.instance.deferFirstFrame();
WidgetsBinding.instance.deferFirstFrameReport();
typeToResourcesFuture.then<void>((Map<Type, dynamic> value) {
RendererBinding.instance.allowFirstFrame();
WidgetsBinding.instance.allowFirstFrameReport();
if (!mounted)
return;
setState(() {
Expand Down

This file was deleted.

0 comments on commit 4c64b71

Please sign in to comment.