Skip to content

Commit

Permalink
Render without rendering rule
Browse files Browse the repository at this point in the history
  • Loading branch information
dkwingsmt committed Jan 22, 2024
1 parent 9209cfb commit d8afe9d
Show file tree
Hide file tree
Showing 8 changed files with 47 additions and 69 deletions.
53 changes: 0 additions & 53 deletions lib/ui/platform_dispatcher.dart
Original file line number Diff line number Diff line change
Expand Up @@ -308,29 +308,6 @@ class PlatformDispatcher {
_invoke(onMetricsChanged, _onMetricsChangedZone);
}

// A debug-only variable that stores the [FlutterView]s for which
// [FlutterView.render] has already been called during the current
// [onBeginFrame]/[onDrawFrame] callback sequence.
//
// It is null outside the scope of those callbacks indicating that calls to
// [FlutterView.render] must be ignored. Furthermore, if a given [FlutterView]
// is already present in this set when its [FlutterView.render] is called
// again, that call must be ignored as a duplicate.
//
// Between [onBeginFrame] and [onDrawFrame] the properties value is
// temporarily stored in `_renderedViewsBetweenCallbacks` so that it survives
// the gap between the two callbacks.
//
// In release build, this variable is null, and therefore the calling rule is
// not enforced. This is because the check might hurt cold startup delay;
// see https://github.com/flutter/engine/pull/46919.
Set<FlutterView>? _debugRenderedViews;
// A debug-only variable that temporarily stores the `_renderedViews` value
// between `_beginFrame` and `_drawFrame`.
//
// In release build, this variable is null.
Set<FlutterView>? _debugRenderedViewsBetweenCallbacks;

/// A callback invoked when any view begins a frame.
///
/// A callback that is invoked to notify the application that it is an
Expand All @@ -351,26 +328,11 @@ class PlatformDispatcher {

// Called from the engine, via hooks.dart
void _beginFrame(int microseconds) {
assert(_debugRenderedViews == null);
assert(_debugRenderedViewsBetweenCallbacks == null);
assert(() {
_debugRenderedViews = <FlutterView>{};
return true;
}());

_invoke1<Duration>(
onBeginFrame,
_onBeginFrameZone,
Duration(microseconds: microseconds),
);

assert(_debugRenderedViews != null);
assert(_debugRenderedViewsBetweenCallbacks == null);
assert(() {
_debugRenderedViewsBetweenCallbacks = _debugRenderedViews;
_debugRenderedViews = null;
return true;
}());
}

/// A callback that is invoked for each frame after [onBeginFrame] has
Expand All @@ -388,22 +350,7 @@ class PlatformDispatcher {

// Called from the engine, via hooks.dart
void _drawFrame() {
assert(_debugRenderedViews == null);
assert(_debugRenderedViewsBetweenCallbacks != null);
assert(() {
_debugRenderedViews = _debugRenderedViewsBetweenCallbacks;
_debugRenderedViewsBetweenCallbacks = null;
return true;
}());

_invoke(onDrawFrame, _onDrawFrameZone);

assert(_debugRenderedViews != null);
assert(_debugRenderedViewsBetweenCallbacks == null);
assert(() {
_debugRenderedViews = null;
return true;
}());
}

/// A callback that is invoked when pointer data is available.
Expand Down
13 changes: 1 addition & 12 deletions lib/ui/window.dart
Original file line number Diff line number Diff line change
Expand Up @@ -372,18 +372,7 @@ class FlutterView {
/// * [RendererBinding], the Flutter framework class which manages layout and
/// painting.
void render(Scene scene, {Size? size}) {
// Duplicated calls or calls outside of onBeginFrame/onDrawFrame (indicated
// by _debugRenderedViews being null) are ignored. See _debugRenderedViews.
// TODO(dkwingsmt): We should change this skip into an assertion.
// https://github.com/flutter/flutter/issues/137073
bool validRender = true;
assert(() {
validRender = platformDispatcher._debugRenderedViews?.add(this) ?? false;
return true;
}());
if (validRender) {
_render(viewId, scene as _NativeScene, size?.width ?? physicalSize.width, size?.height ?? physicalSize.height);
}
_render(viewId, scene as _NativeScene, size?.width ?? physicalSize.width, size?.height ?? physicalSize.height);
}

@Native<Void Function(Int64, Pointer<Void>, Double, Double)>(symbol: 'PlatformConfigurationNativeApi::Render')
Expand Down
4 changes: 4 additions & 0 deletions runtime/runtime_controller.cc
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,10 @@ bool RuntimeController::RemoveView(int64_t view_id) {
return false;
}

size_t RuntimeController::NumViews() const {
return platform_data_.viewport_metrics_for_views.size();
}

bool RuntimeController::SetViewportMetrics(int64_t view_id,
const ViewportMetrics& metrics) {
TRACE_EVENT0("flutter", "SetViewportMetrics");
Expand Down
5 changes: 5 additions & 0 deletions runtime/runtime_controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,11 @@ class RuntimeController : public PlatformConfigurationClient {
///
bool RemoveView(int64_t view_id);

//----------------------------------------------------------------------------
/// @brief Return the number of views registered.
///
size_t NumViews() const;

//----------------------------------------------------------------------------
/// @brief Forward the specified viewport metrics to the running isolate.
/// If the isolate is not running, these metrics will be saved and
Expand Down
14 changes: 11 additions & 3 deletions shell/common/animator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,9 @@ void Animator::BeginFrame(
}

void Animator::EndFrame() {
FML_CHECK(frame_timings_recorder_ != nullptr);
if (frame_timings_recorder_ == nullptr) {
return;
}
if (!layer_trees_tasks_.empty()) {
// The build is completed in OnAnimatorBeginFrame.
frame_timings_recorder_->RecordBuildEnd(fml::TimePoint::Now());
Expand Down Expand Up @@ -179,10 +181,16 @@ void Animator::EndFrame() {
void Animator::Render(int64_t view_id,
std::unique_ptr<flutter::LayerTree> layer_tree,
float device_pixel_ratio) {
FML_CHECK(frame_timings_recorder_ != nullptr);

has_rendered_ = true;

if (!frame_timings_recorder_) {
// Framework can directly call render with a built scene.
frame_timings_recorder_ = std::make_unique<FrameTimingsRecorder>();
const fml::TimePoint placeholder_time = fml::TimePoint::Now();
frame_timings_recorder_->RecordVsync(placeholder_time, placeholder_time);
frame_timings_recorder_->RecordBuildStart(placeholder_time);
}

TRACE_EVENT_WITH_FRAME_NUMBER(frame_timings_recorder_, "flutter",
"Animator::Render", /*flow_id_count=*/0,
/*flow_ids=*/nullptr);
Expand Down
3 changes: 2 additions & 1 deletion shell/common/animator.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,14 +89,15 @@ class Animator final {
// rendering.
void EnqueueTraceFlowId(uint64_t trace_flow_id);

void EndFrame();

private:
// Animator's work during a vsync is split into two methods, BeginFrame and
// EndFrame. The two methods should be called synchronously back-to-back to
// avoid being interrupted by a regular vsync. The reason to split them is to
// allow ShellTest::PumpOneFrame to insert a Render in between.

void BeginFrame(std::unique_ptr<FrameTimingsRecorder> frame_timings_recorder);
void EndFrame();

bool CanReuseLastLayerTrees();

Expand Down
18 changes: 18 additions & 0 deletions shell/common/engine.cc
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ Engine::RunStatus Engine::Run(RunConfiguration configuration) {
}

void Engine::BeginFrame(fml::TimePoint frame_time, uint64_t frame_number) {
MarkAsEndOfFrame();
runtime_controller_->BeginFrame(frame_time, frame_number);
}

Expand Down Expand Up @@ -475,6 +476,23 @@ void Engine::Render(int64_t view_id,
}

animator_->Render(view_id, std::move(layer_tree), device_pixel_ratio);
rendered_views_during_frame_.insert(view_id);
SubmitFrameIfEndOfFrame();
}

void Engine::MarkAsEndOfFrame() {
rendered_views_during_frame_.clear();
}

void Engine::SubmitFrameIfEndOfFrame() {
if (!runtime_controller_) {
return;
}
if (rendered_views_during_frame_.size() != 0 &&
rendered_views_during_frame_.size() == runtime_controller_->NumViews()) {
animator_->EndFrame();
MarkAsEndOfFrame();
}
}

void Engine::UpdateSemantics(SemanticsNodeUpdates update,
Expand Down
6 changes: 6 additions & 0 deletions shell/common/engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -1014,6 +1014,10 @@ class Engine final : public RuntimeDelegate, PointerDataDispatcher::Delegate {

bool GetAssetAsBuffer(const std::string& name, std::vector<uint8_t>* data);

void MarkAsEndOfFrame();

void SubmitFrameIfEndOfFrame();

friend class testing::ShellTest;

Engine::Delegate& delegate_;
Expand All @@ -1026,6 +1030,8 @@ class Engine final : public RuntimeDelegate, PointerDataDispatcher::Delegate {
// is destructed first.
std::unique_ptr<PointerDataDispatcher> pointer_data_dispatcher_;

std::unordered_set<uint64_t> rendered_views_during_frame_;

std::string last_entry_point_;
std::string last_entry_point_library_;
std::vector<std::string> last_entry_point_args_;
Expand Down

0 comments on commit d8afe9d

Please sign in to comment.