1 | // Copyright 2013 The Flutter Authors. All rights reserved. |
2 | // Use of this source code is governed by a BSD-style license that can be |
3 | // found in the LICENSE file. |
4 | |
5 | #include "flutter/shell/common/shell_io_manager.h" |
6 | |
7 | #include "flutter/fml/build_config.h" |
8 | #include "flutter/fml/message_loop.h" |
9 | #include "flutter/shell/common/persistent_cache.h" |
10 | #include "third_party/skia/include/gpu/gl/GrGLInterface.h" |
11 | |
12 | namespace flutter { |
13 | |
14 | sk_sp<GrDirectContext> ShellIOManager::CreateCompatibleResourceLoadingContext( |
15 | GrBackend backend, |
16 | sk_sp<const GrGLInterface> gl_interface) { |
17 | if (backend != GrBackend::kOpenGL_GrBackend) { |
18 | return nullptr; |
19 | } |
20 | |
21 | GrContextOptions options = {}; |
22 | |
23 | if (PersistentCache::cache_sksl()) { |
24 | FML_LOG(INFO) << "Cache SkSL" ; |
25 | options.fShaderCacheStrategy = GrContextOptions::ShaderCacheStrategy::kSkSL; |
26 | } |
27 | PersistentCache::MarkStrategySet(); |
28 | |
29 | options.fPersistentCache = PersistentCache::GetCacheForProcess(); |
30 | |
31 | // There is currently a bug with doing GPU YUV to RGB conversions on the IO |
32 | // thread. The necessary work isn't being flushed or synchronized with the |
33 | // other threads correctly, so the textures end up blank. For now, suppress |
34 | // that feature, which will cause texture uploads to do CPU YUV conversion. |
35 | // A similar work-around is also used in shell/gpu/gpu_surface_gl.cc. |
36 | options.fDisableGpuYUVConversion = true; |
37 | |
38 | // To get video playback on the widest range of devices, we limit Skia to |
39 | // ES2 shading language when the ES3 external image extension is missing. |
40 | options.fPreferExternalImagesOverES3 = true; |
41 | |
42 | #if !OS_FUCHSIA |
43 | if (auto context = GrDirectContext::MakeGL(gl_interface, options)) { |
44 | // Do not cache textures created by the image decoder. These textures |
45 | // should be deleted when they are no longer referenced by an SkImage. |
46 | context->setResourceCacheLimits(0, 0); |
47 | return context; |
48 | } |
49 | #endif |
50 | |
51 | return nullptr; |
52 | } |
53 | |
54 | ShellIOManager::ShellIOManager( |
55 | sk_sp<GrDirectContext> resource_context, |
56 | std::shared_ptr<fml::SyncSwitch> is_gpu_disabled_sync_switch, |
57 | fml::RefPtr<fml::TaskRunner> unref_queue_task_runner) |
58 | : resource_context_(std::move(resource_context)), |
59 | resource_context_weak_factory_( |
60 | resource_context_ |
61 | ? std::make_unique<fml::WeakPtrFactory<GrDirectContext>>( |
62 | resource_context_.get()) |
63 | : nullptr), |
64 | unref_queue_(fml::MakeRefCounted<flutter::SkiaUnrefQueue>( |
65 | std::move(unref_queue_task_runner), |
66 | fml::TimeDelta::FromMilliseconds(8), |
67 | GetResourceContext())), |
68 | weak_factory_(this), |
69 | is_gpu_disabled_sync_switch_(is_gpu_disabled_sync_switch) { |
70 | if (!resource_context_) { |
71 | #ifndef OS_FUCHSIA |
72 | FML_DLOG(WARNING) << "The IO manager was initialized without a resource " |
73 | "context. Async texture uploads will be disabled. " |
74 | "Expect performance degradation." ; |
75 | #endif // OS_FUCHSIA |
76 | } |
77 | } |
78 | |
79 | ShellIOManager::~ShellIOManager() { |
80 | // Last chance to drain the IO queue as the platform side reference to the |
81 | // underlying OpenGL context may be going away. |
82 | is_gpu_disabled_sync_switch_->Execute( |
83 | fml::SyncSwitch::Handlers().SetIfFalse([&] { unref_queue_->Drain(); })); |
84 | } |
85 | |
86 | void ShellIOManager::NotifyResourceContextAvailable( |
87 | sk_sp<GrDirectContext> resource_context) { |
88 | // The resource context needs to survive as long as we have Dart objects |
89 | // referencing. We shouldn't ever need to replace it if we have one - unless |
90 | // we've somehow shut down the Dart VM and started a new one fresh. |
91 | if (!resource_context_) { |
92 | UpdateResourceContext(std::move(resource_context)); |
93 | } |
94 | } |
95 | |
96 | void ShellIOManager::UpdateResourceContext( |
97 | sk_sp<GrDirectContext> resource_context) { |
98 | resource_context_ = std::move(resource_context); |
99 | resource_context_weak_factory_ = |
100 | resource_context_ |
101 | ? std::make_unique<fml::WeakPtrFactory<GrDirectContext>>( |
102 | resource_context_.get()) |
103 | : nullptr; |
104 | } |
105 | |
106 | fml::WeakPtr<ShellIOManager> ShellIOManager::GetWeakPtr() { |
107 | return weak_factory_.GetWeakPtr(); |
108 | } |
109 | |
110 | // |IOManager| |
111 | fml::WeakPtr<GrDirectContext> ShellIOManager::GetResourceContext() const { |
112 | return resource_context_weak_factory_ |
113 | ? resource_context_weak_factory_->GetWeakPtr() |
114 | : fml::WeakPtr<GrDirectContext>(); |
115 | } |
116 | |
117 | // |IOManager| |
118 | fml::RefPtr<flutter::SkiaUnrefQueue> ShellIOManager::GetSkiaUnrefQueue() const { |
119 | return unref_queue_; |
120 | } |
121 | |
122 | // |IOManager| |
123 | fml::WeakPtr<IOManager> ShellIOManager::GetWeakIOManager() const { |
124 | return weak_factory_.GetWeakPtr(); |
125 | } |
126 | |
127 | // |IOManager| |
128 | std::shared_ptr<fml::SyncSwitch> ShellIOManager::GetIsGpuDisabledSyncSwitch() { |
129 | return is_gpu_disabled_sync_switch_; |
130 | } |
131 | |
132 | } // namespace flutter |
133 | |