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
12namespace flutter {
13
14sk_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
54ShellIOManager::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
79ShellIOManager::~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
86void 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
96void 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
106fml::WeakPtr<ShellIOManager> ShellIOManager::GetWeakPtr() {
107 return weak_factory_.GetWeakPtr();
108}
109
110// |IOManager|
111fml::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|
118fml::RefPtr<flutter::SkiaUnrefQueue> ShellIOManager::GetSkiaUnrefQueue() const {
119 return unref_queue_;
120}
121
122// |IOManager|
123fml::WeakPtr<IOManager> ShellIOManager::GetWeakIOManager() const {
124 return weak_factory_.GetWeakPtr();
125}
126
127// |IOManager|
128std::shared_ptr<fml::SyncSwitch> ShellIOManager::GetIsGpuDisabledSyncSwitch() {
129 return is_gpu_disabled_sync_switch_;
130}
131
132} // namespace flutter
133