Revert "Add option to delay rendering the first frame (#45135)" (#45385)

This reverts commit d285b8843fce6cf039eb197a09b01ca5cc00d92b.
diff --git a/packages/flutter/lib/src/rendering/binding.dart b/packages/flutter/lib/src/rendering/binding.dart
index 9cfb575..adf1037 100644
--- a/packages/flutter/lib/src/rendering/binding.dart
+++ b/packages/flutter/lib/src/rendering/binding.dart
@@ -283,53 +283,6 @@
     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
@@ -391,11 +344,8 @@
     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
diff --git a/packages/flutter/lib/src/widgets/binding.dart b/packages/flutter/lib/src/widgets/binding.dart
index 1fd7d81..c4eb958 100644
--- a/packages/flutter/lib/src/widgets/binding.dart
+++ b/packages/flutter/lib/src/widgets/binding.dart
@@ -572,6 +572,9 @@
   }
 
   bool _needToReportFirstFrame = true;
+  int _deferFirstFrameReportCount = 0;
+  bool get _reportFirstFrame => _deferFirstFrameReportCount == 0;
+
 
   final Completer<void> _firstFrameCompleter = Completer<void>();
 
@@ -597,6 +600,11 @@
 
   /// 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`.
   ///
@@ -608,30 +616,27 @@
   /// 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;
     }
   }
 
@@ -748,23 +753,18 @@
       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);
     }
 
@@ -780,14 +780,11 @@
       }());
     }
     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
@@ -835,9 +832,12 @@
       return true;
     }());
 
+    deferFirstFrameReport();
     if (renderViewElement != null)
       buildOwner.reassemble(renderViewElement);
-    return super.performReassemble();
+    return super.performReassemble().then((void value) {
+      allowFirstFrameReport();
+    });
   }
 }
 
diff --git a/packages/flutter/lib/src/widgets/localizations.dart b/packages/flutter/lib/src/widgets/localizations.dart
index 29196b3..0cc93a8 100644
--- a/packages/flutter/lib/src/widgets/localizations.dart
+++ b/packages/flutter/lib/src/widgets/localizations.dart
@@ -6,7 +6,6 @@
 import 'dart:ui' show Locale;
 
 import 'package:flutter/foundation.dart';
-import 'package:flutter/rendering.dart';
 
 import 'basic.dart';
 import 'binding.dart';
@@ -520,9 +519,9 @@
       // 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(() {
diff --git a/packages/flutter/test/widgets/binding_deferred_first_frame_test.dart b/packages/flutter/test/widgets/binding_deferred_first_frame_test.dart
deleted file mode 100644
index 0f6d019..0000000
--- a/packages/flutter/test/widgets/binding_deferred_first_frame_test.dart
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import 'dart:async';
-
-import 'package:flutter/rendering.dart';
-import 'package:flutter_test/flutter_test.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter/widgets.dart';
-
-const String _actualContent = 'Actual Content';
-const String _loading = 'Loading...';
-
-void main() {
-  testWidgets('deferFirstFrame/allowFirstFrame stops sending frames to engine', (WidgetTester tester) async {
-    expect(RendererBinding.instance.sendFramesToEngine, isTrue);
-
-    final Completer<void> completer = Completer<void>();
-    await tester.pumpWidget(
-      Directionality(
-        textDirection: TextDirection.ltr,
-        child: _DeferringWidget(
-          key: UniqueKey(),
-          loader: completer.future,
-        ),
-      ),
-    );
-    final _DeferringWidgetState state = tester.state<_DeferringWidgetState>(find.byType(_DeferringWidget));
-
-    expect(find.text(_loading), findsOneWidget);
-    expect(find.text(_actualContent), findsNothing);
-    expect(RendererBinding.instance.sendFramesToEngine, isFalse);
-
-    await tester.pump();
-    expect(find.text(_loading), findsOneWidget);
-    expect(find.text(_actualContent), findsNothing);
-    expect(RendererBinding.instance.sendFramesToEngine, isFalse);
-    expect(state.doneLoading, isFalse);
-
-    // Complete the future to start sending frames.
-    completer.complete();
-    await tester.idle();
-    expect(state.doneLoading, isTrue);
-    expect(RendererBinding.instance.sendFramesToEngine, isTrue);
-
-    await tester.pump();
-    expect(find.text(_loading), findsNothing);
-    expect(find.text(_actualContent), findsOneWidget);
-    expect(RendererBinding.instance.sendFramesToEngine, isTrue);
-  });
-}
-
-class _DeferringWidget extends StatefulWidget {
-  const _DeferringWidget({Key key, this.loader}) : super(key: key);
-
-  final Future<void> loader;
-
-  @override
-  State<_DeferringWidget> createState() => _DeferringWidgetState();
-}
-
-class _DeferringWidgetState extends State<_DeferringWidget> {
-  bool doneLoading = false;
-
-  @override
-  void initState() {
-    super.initState();
-    RendererBinding.instance.deferFirstFrame();
-    widget.loader.then((_) {
-      setState(() {
-        doneLoading = true;
-        RendererBinding.instance.allowFirstFrame();
-      });
-    });
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    return doneLoading
-        ? const Text(_actualContent)
-        : const Text(_loading);
-  }
-}