@@ -860,25 +860,34 @@ void Engine::WarmupSkps(
860
860
SkISize size,
861
861
std::shared_ptr<flutter::AssetManager> asset_manager,
862
862
std::optional<const std::vector<std::string>> skp_names,
863
- std::optional<std::function<void (uint32_t )>> completion_callback) {
864
- // We use a raw pointer here because we want to keep this alive until all gpu
865
- // work is done and the callbacks skia takes for this are function pointers
866
- // so we are unable to use a lambda that captures the smart pointer.
867
- SurfaceProducerSurface* skp_warmup_surface =
868
- surface_producer->ProduceOffscreenSurface (size).release ();
869
- if (!skp_warmup_surface) {
870
- FML_LOG (ERROR) << " Failed to create offscreen warmup surface" ;
871
- // Tell client that zero shaders were warmed up because warmup failed.
872
- if (completion_callback.has_value () && completion_callback.value ()) {
873
- completion_callback.value ()(0 );
863
+ std::optional<std::function<void (uint32_t )>> maybe_completion_callback) {
864
+ // Wrap the optional validity checks up in a lambda to simplify the various
865
+ // callsites below
866
+ auto completion_callback = [maybe_completion_callback](uint32_t skp_count) {
867
+ if (maybe_completion_callback.has_value () &&
868
+ maybe_completion_callback.value ()) {
869
+ maybe_completion_callback.value ()(skp_count);
874
870
}
875
- return ;
876
- }
871
+ };
872
+
873
+ // We use this bizzare raw pointer to a smart pointer thing here because we
874
+ // want to keep the surface alive until all gpu work is done and the
875
+ // callbacks skia takes for this are function pointers so we are unable to
876
+ // use a lambda that captures the smart pointer. We need two levels of
877
+ // indirection because it needs to be the same across all invocations of the
878
+ // raster task lambda from a single invocation of WarmupSkps, but be
879
+ // different across different invocations of WarmupSkps (so we cant
880
+ // statically initialialize it in the lambda itself). Basically the result
881
+ // of a mashup of wierd call dynamics, multithreading, and lifecycle
882
+ // management with C style Skia callbacks.
883
+ std::unique_ptr<SurfaceProducerSurface>* skp_warmup_surface =
884
+ new std::unique_ptr<SurfaceProducerSurface>(nullptr );
877
885
878
886
// tell concurrent task runner to deserialize all skps available from
879
887
// the asset manager
880
- concurrent_task_runner->PostTask ([raster_task_runner, skp_warmup_surface,
881
- surface_producer, asset_manager, skp_names,
888
+ concurrent_task_runner->PostTask ([raster_task_runner, size,
889
+ skp_warmup_surface, surface_producer,
890
+ asset_manager, skp_names,
882
891
completion_callback]() {
883
892
TRACE_DURATION (" flutter" , " DeserializeSkps" );
884
893
std::vector<std::unique_ptr<fml::Mapping>> skp_mappings;
@@ -895,6 +904,13 @@ void Engine::WarmupSkps(
895
904
skp_mappings = asset_manager->GetAsMappings (" .*\\ .skp$" , " shaders" );
896
905
}
897
906
907
+ if (skp_mappings.size () == 0 ) {
908
+ FML_LOG (WARNING)
909
+ << " Engine::WarmupSkps got zero SKP mappings, returning early" ;
910
+ completion_callback (0 );
911
+ return ;
912
+ }
913
+
898
914
size_t total_size = 0 ;
899
915
for (auto & mapping : skp_mappings) {
900
916
total_size += mapping->GetSize ();
@@ -920,20 +936,35 @@ void Engine::WarmupSkps(
920
936
921
937
// Tell raster task runner to warmup have the compositor
922
938
// context warm up the newly deserialized picture
923
- raster_task_runner->PostTask ([skp_warmup_surface, picture ,
939
+ raster_task_runner->PostTask ([picture, skp_warmup_surface, size ,
924
940
surface_producer, completion_callback, i,
925
941
count = skp_mappings.size ()] {
926
942
TRACE_DURATION (" flutter" , " WarmupSkp" );
927
- skp_warmup_surface->GetSkiaSurface ()->getCanvas ()->drawPicture (picture);
943
+ if (*skp_warmup_surface == nullptr ) {
944
+ skp_warmup_surface->reset (
945
+ surface_producer->ProduceOffscreenSurface (size).release ());
946
+
947
+ if (*skp_warmup_surface == nullptr ) {
948
+ FML_LOG (ERROR) << " Failed to create offscreen warmup surface" ;
949
+ // Tell client that zero shaders were warmed up because warmup
950
+ // failed.
951
+ completion_callback (0 );
952
+ return ;
953
+ }
954
+ }
955
+
956
+ // Do the actual warmup
957
+ (*skp_warmup_surface)
958
+ ->GetSkiaSurface ()
959
+ ->getCanvas ()
960
+ ->drawPicture (picture);
928
961
929
962
if (i == count - 1 ) {
930
963
// We call this here instead of inside fFinishedProc below because
931
964
// we want to unblock the dart animation code as soon as the raster
932
965
// thread is free to enque work, rather than waiting for the GPU work
933
966
// itself to finish.
934
- if (completion_callback.has_value () && completion_callback.value ()) {
935
- completion_callback.value ()(count);
936
- }
967
+ completion_callback (count);
937
968
}
938
969
939
970
if (surface_producer->gr_context ()) {
0 commit comments