Flutter Engine
The Flutter Engine
Recording.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2021 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
9
10#include "src/core/SkChecksum.h"
22
23#include <unordered_set>
24
25using namespace skia_private;
26
27namespace skgpu::graphite {
28
29Recording::Recording(uint32_t uniqueID,
30 uint32_t recorderID,
31 std::unordered_set<sk_sp<TextureProxy>, ProxyHash>&& nonVolatileLazyProxies,
32 std::unordered_set<sk_sp<TextureProxy>, ProxyHash>&& volatileLazyProxies,
33 std::unique_ptr<LazyProxyData> targetProxyData,
34 TArray<sk_sp<RefCntedCallback>>&& finishedProcs)
35 : fUniqueID(uniqueID)
36 , fRecorderID(recorderID)
37 , fRootTaskList(new TaskList)
38 , fNonVolatileLazyProxies(std::move(nonVolatileLazyProxies))
39 , fVolatileLazyProxies(std::move(volatileLazyProxies))
40 , fTargetProxyData(std::move(targetProxyData))
41 , fFinishedProcs(std::move(finishedProcs)) {}
42
43Recording::~Recording() {
44 // Any finished procs that haven't been passed to a CommandBuffer fail
45 this->priv().setFailureResultForFinishedProcs();
46}
47
48std::size_t Recording::ProxyHash::operator()(const sk_sp<TextureProxy> &proxy) const {
49 return SkGoodHash()(proxy.get());
50}
51
52Recording::LazyProxyData::LazyProxyData(const TextureInfo& textureInfo) {
53 fTargetProxy = TextureProxy::MakeFullyLazy(
54 textureInfo, skgpu::Budgeted::kNo, Volatile::kYes, [this](ResourceProvider*) {
55 SkASSERT(SkToBool(fTarget));
56 return std::move(fTarget);
57 });
58}
59
60TextureProxy* Recording::LazyProxyData::lazyProxy() { return fTargetProxy.get(); }
61
62sk_sp<TextureProxy> Recording::LazyProxyData::refLazyProxy() { return fTargetProxy; }
63
64bool Recording::LazyProxyData::lazyInstantiate(ResourceProvider* resourceProvider,
66 fTarget = std::move(texture);
67 return fTargetProxy->lazyInstantiate(resourceProvider);
68}
69
70////////////////////////////////////////////////////////////////////////////////
71bool RecordingPriv::hasNonVolatileLazyProxies() const {
72 return !fRecording->fNonVolatileLazyProxies.empty();
73}
74
75bool RecordingPriv::instantiateNonVolatileLazyProxies(ResourceProvider* resourceProvider) {
76 SkASSERT(this->hasNonVolatileLazyProxies());
77
78 for (const auto& proxy : fRecording->fNonVolatileLazyProxies) {
79 if (!proxy->lazyInstantiate(resourceProvider)) {
80 return false;
81 }
82 }
83
84 // Note: once all the lazy proxies have been instantiated, that's it - there are no more
85 // chances to instantiate.
86 fRecording->fNonVolatileLazyProxies.clear();
87 return true;
88}
89
90bool RecordingPriv::hasVolatileLazyProxies() const {
91 return !fRecording->fVolatileLazyProxies.empty();
92}
93
94bool RecordingPriv::instantiateVolatileLazyProxies(ResourceProvider* resourceProvider) {
95 SkASSERT(this->hasVolatileLazyProxies());
96
97 for (const auto& proxy : fRecording->fVolatileLazyProxies) {
98 if (!proxy->lazyInstantiate(resourceProvider)) {
99 return false;
100 }
101 }
102
103 return true;
104}
105
106void RecordingPriv::deinstantiateVolatileLazyProxies() {
107 if (!this->hasVolatileLazyProxies()) {
108 return;
109 }
110
111 for (const auto& proxy : fRecording->fVolatileLazyProxies) {
112 SkASSERT(proxy->isVolatile());
113 proxy->deinstantiate();
114 }
115}
116
117void RecordingPriv::setFailureResultForFinishedProcs() {
118 for (int i = 0; i < fRecording->fFinishedProcs.size(); ++i) {
119 fRecording->fFinishedProcs[i]->setFailureResult();
120 }
121 fRecording->fFinishedProcs.clear();
122}
123
124bool RecordingPriv::addCommands(Context* context,
125 CommandBuffer* commandBuffer,
126 Surface* targetSurface,
127 SkIVector targetTranslation) {
128 AutoDeinstantiateTextureProxy autoDeinstantiateTargetProxy(
129 fRecording->fTargetProxyData ? fRecording->fTargetProxyData->lazyProxy() : nullptr);
130
131 const Texture* replayTarget = nullptr;
132 ResourceProvider* resourceProvider = context->priv().resourceProvider();
133 SkASSERT(!SkToBool(fRecording->fTargetProxyData) || SkToBool(targetSurface));
134 if (fRecording->fTargetProxyData) {
135 if (!targetSurface) {
136 SKGPU_LOG_E("No surface provided to instantiate target texture proxy.");
137 return false;
138 }
139 TextureProxy* surfaceTexture = targetSurface->backingTextureProxy();
140 if (!surfaceTexture->instantiate(resourceProvider)) {
141 SKGPU_LOG_E("Could not instantiate target texture proxy.");
142 return false;
143 }
144 if (!fRecording->fTargetProxyData->lazyInstantiate(resourceProvider,
145 surfaceTexture->refTexture())) {
146 SKGPU_LOG_E("Could not instantiate deferred texture proxy.");
147 return false;
148 }
149 replayTarget = surfaceTexture->texture();
150 }
151
152 for (size_t i = 0; i < fRecording->fExtraResourceRefs.size(); ++i) {
153 commandBuffer->trackResource(fRecording->fExtraResourceRefs[i]);
154 }
155
156 // There's no need to differentiate kSuccess and kDiscard at the root list level; if every task
157 // is discarded, the Recording will automatically be a no-op on replay while still correctly
158 // notifying any finish procs the client may have added.
159 if (fRecording->fRootTaskList->addCommands(
160 context, commandBuffer, {replayTarget, targetTranslation}) == Task::Status::kFail) {
161 return false;
162 }
163 for (int i = 0; i < fRecording->fFinishedProcs.size(); ++i) {
164 commandBuffer->addFinishedProc(std::move(fRecording->fFinishedProcs[i]));
165 }
166 fRecording->fFinishedProcs.clear();
167
168 return true;
169}
170
171void RecordingPriv::addResourceRef(sk_sp<Resource> resource) {
172 fRecording->fExtraResourceRefs.push_back(std::move(resource));
173}
174
175void RecordingPriv::addTask(sk_sp<Task> task) {
176 fRecording->fRootTaskList->add(std::move(task));
177}
178
179void RecordingPriv::addTasks(TaskList&& tasks) {
180 fRecording->fRootTaskList->add(std::move(tasks));
181}
182
183#if defined(GRAPHITE_TEST_UTILS)
184bool RecordingPriv::isTargetProxyInstantiated() const {
185 return fRecording->fTargetProxyData->lazyProxy()->isInstantiated();
186}
187
188int RecordingPriv::numVolatilePromiseImages() const {
189 return fRecording->fVolatileLazyProxies.size();
190}
191
192int RecordingPriv::numNonVolatilePromiseImages() const {
193 return fRecording->fNonVolatileLazyProxies.size();
194}
195
196bool RecordingPriv::hasTasks() const {
197 return fRecording->fRootTaskList->hasTasks();
198}
199#endif
200
201} // namespace skgpu::graphite
#define SKGPU_LOG_E(fmt,...)
Definition: Log.h:38
#define SkASSERT(cond)
Definition: SkAssert.h:116
static SkString resource(SkPDFResourceType type, int index)
static constexpr bool SkToBool(const T &x)
Definition: SkTo.h:35
T * get() const
Definition: SkRefCnt.h:303
void trackResource(sk_sp< Resource > resource)
void addFinishedProc(sk_sp< RefCntedCallback > finishedProc)
ResourceProvider * resourceProvider() const
Definition: ContextPriv.h:49
TextureProxy * backingTextureProxy() const
bool instantiate(ResourceProvider *)
sk_sp< Texture > refTexture() const
const Texture * texture() const
FlPixelBufferTexturePrivate * priv
FlTexture * texture
Definition: ref_ptr.h:256