From 3c8686129520653c3b76dfa63c29ffc95b90eda9 Mon Sep 17 00:00:00 2001 From: zhongwuzw Date: Thu, 15 Oct 2020 17:49:52 +0800 Subject: [PATCH 1/3] Skip unnecessary canvas operations --- .../framework/Source/FlutterPlatformViews.mm | 134 +++++++++--------- 1 file changed, 69 insertions(+), 65 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index c0c185c6ee4b7..0a30ca08731f0 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -471,79 +471,83 @@ DisposeViews(); - SkCanvas* background_canvas = frame->SkiaCanvas(); + auto did_submit = true; + auto num_platform_views = composition_order_.size(); - // Resolve all pending GPU operations before allocating a new surface. - background_canvas->flush(); - // Clipping the background canvas before drawing the picture recorders requires to - // save and restore the clip context. - SkAutoCanvasRestore save(background_canvas, /*doSave=*/true); // Maps a platform view id to a vector of `FlutterPlatformViewLayer`. LayersMap platform_view_layers; - auto did_submit = true; - auto num_platform_views = composition_order_.size(); - - for (size_t i = 0; i < num_platform_views; i++) { - int64_t platform_view_id = composition_order_[i]; - sk_sp rtree = platform_view_rtrees_[platform_view_id]; - sk_sp picture = picture_recorders_[platform_view_id]->finishRecordingAsPicture(); - - // Check if the current picture contains overlays that intersect with the - // current platform view or any of the previous platform views. - for (size_t j = i + 1; j > 0; j--) { - int64_t current_platform_view_id = composition_order_[j - 1]; - SkRect platform_view_rect = GetPlatformViewRect(current_platform_view_id); - std::list intersection_rects = - rtree->searchNonOverlappingDrawnRects(platform_view_rect); - auto allocation_size = intersection_rects.size(); - - // For testing purposes, the overlay id is used to find the overlay view. - // This is the index of the layer for the current platform view. - auto overlay_id = platform_view_layers[current_platform_view_id].size(); - - // If the max number of allocations per platform view is exceeded, - // then join all the rects into a single one. - // - // TODO(egarciad): Consider making this configurable. - // https://github.com/flutter/flutter/issues/52510 - if (allocation_size > kMaxLayerAllocations) { - SkRect joined_rect; - for (const SkRect& rect : intersection_rects) { - joined_rect.join(rect); + if (num_platform_views > 0) { + SkCanvas* background_canvas = frame->SkiaCanvas(); + + // Resolve all pending GPU operations before allocating a new surface. + background_canvas->flush(); + // Clipping the background canvas before drawing the picture recorders requires to + // save and restore the clip context. + SkAutoCanvasRestore save(background_canvas, /*doSave=*/true); + + for (size_t i = 0; i < num_platform_views; i++) { + int64_t platform_view_id = composition_order_[i]; + sk_sp rtree = platform_view_rtrees_[platform_view_id]; + sk_sp picture = picture_recorders_[platform_view_id]->finishRecordingAsPicture(); + + // Check if the current picture contains overlays that intersect with the + // current platform view or any of the previous platform views. + for (size_t j = i + 1; j > 0; j--) { + int64_t current_platform_view_id = composition_order_[j - 1]; + SkRect platform_view_rect = GetPlatformViewRect(current_platform_view_id); + std::list intersection_rects = + rtree->searchNonOverlappingDrawnRects(platform_view_rect); + auto allocation_size = intersection_rects.size(); + + // For testing purposes, the overlay id is used to find the overlay view. + // This is the index of the layer for the current platform view. + auto overlay_id = platform_view_layers[current_platform_view_id].size(); + + // If the max number of allocations per platform view is exceeded, + // then join all the rects into a single one. + // + // TODO(egarciad): Consider making this configurable. + // https://github.com/flutter/flutter/issues/52510 + if (allocation_size > kMaxLayerAllocations) { + SkRect joined_rect; + for (const SkRect& rect : intersection_rects) { + joined_rect.join(rect); + } + // Replace the rects in the intersection rects list for a single rect that is + // the union of all the rects in the list. + intersection_rects.clear(); + intersection_rects.push_back(joined_rect); + } + for (SkRect& joined_rect : intersection_rects) { + // Get the intersection rect between the current rect + // and the platform view rect. + joined_rect.intersect(platform_view_rect); + // Subpixels in the platform may not align with the canvas subpixels. + // To workaround it, round the floating point bounds and make the rect slighly larger. + // For example, {0.3, 0.5, 3.1, 4.7} becomes {0, 0, 4, 5}. + joined_rect.setLTRB(std::floor(joined_rect.left()), std::floor(joined_rect.top()), + std::ceil(joined_rect.right()), std::ceil(joined_rect.bottom())); + // Clip the background canvas, so it doesn't contain any of the pixels drawn + // on the overlay layer. + background_canvas->clipRect(joined_rect, SkClipOp::kDifference); + // Get a new host layer. + std::shared_ptr layer = GetLayer(gr_context, // + ios_context, // + picture, // + joined_rect, // + current_platform_view_id, // + overlay_id // + ); + did_submit &= layer->did_submit_last_frame; + platform_view_layers[current_platform_view_id].push_back(layer); + overlay_id++; } - // Replace the rects in the intersection rects list for a single rect that is - // the union of all the rects in the list. - intersection_rects.clear(); - intersection_rects.push_back(joined_rect); - } - for (SkRect& joined_rect : intersection_rects) { - // Get the intersection rect between the current rect - // and the platform view rect. - joined_rect.intersect(platform_view_rect); - // Subpixels in the platform may not align with the canvas subpixels. - // To workaround it, round the floating point bounds and make the rect slighly larger. - // For example, {0.3, 0.5, 3.1, 4.7} becomes {0, 0, 4, 5}. - joined_rect.setLTRB(std::floor(joined_rect.left()), std::floor(joined_rect.top()), - std::ceil(joined_rect.right()), std::ceil(joined_rect.bottom())); - // Clip the background canvas, so it doesn't contain any of the pixels drawn - // on the overlay layer. - background_canvas->clipRect(joined_rect, SkClipOp::kDifference); - // Get a new host layer. - std::shared_ptr layer = GetLayer(gr_context, // - ios_context, // - picture, // - joined_rect, // - current_platform_view_id, // - overlay_id // - ); - did_submit &= layer->did_submit_last_frame; - platform_view_layers[current_platform_view_id].push_back(layer); - overlay_id++; } + background_canvas->drawPicture(picture); } - background_canvas->drawPicture(picture); } + // If a layer was allocated in the previous frame, but it's not used in the current frame, // then it can be removed from the scene. RemoveUnusedLayers(); From 5ac5a637380a218420df3d3558e516a91385ebcc Mon Sep 17 00:00:00 2001 From: zhongwuzw Date: Thu, 15 Oct 2020 18:18:22 +0800 Subject: [PATCH 2/3] clang-format --- .../darwin/ios/framework/Source/FlutterPlatformViews.mm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index 0a30ca08731f0..f87fa8e97cce9 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -497,7 +497,7 @@ int64_t current_platform_view_id = composition_order_[j - 1]; SkRect platform_view_rect = GetPlatformViewRect(current_platform_view_id); std::list intersection_rects = - rtree->searchNonOverlappingDrawnRects(platform_view_rect); + rtree->searchNonOverlappingDrawnRects(platform_view_rect); auto allocation_size = intersection_rects.size(); // For testing purposes, the overlay id is used to find the overlay view. @@ -538,7 +538,7 @@ joined_rect, // current_platform_view_id, // overlay_id // - ); + ); did_submit &= layer->did_submit_last_frame; platform_view_layers[current_platform_view_id].push_back(layer); overlay_id++; From f0f2f16f9604db234b96513f5a4415e8c9d5806f Mon Sep 17 00:00:00 2001 From: zhongwuzw Date: Tue, 27 Oct 2020 14:26:57 +0800 Subject: [PATCH 3/3] Empty line --- .../platform/darwin/ios/framework/Source/FlutterPlatformViews.mm | 1 - 1 file changed, 1 deletion(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index f87fa8e97cce9..fd36b7b32b3a5 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -479,7 +479,6 @@ if (num_platform_views > 0) { SkCanvas* background_canvas = frame->SkiaCanvas(); - // Resolve all pending GPU operations before allocating a new surface. background_canvas->flush(); // Clipping the background canvas before drawing the picture recorders requires to