Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
AsyncReadTypes.h
Go to the documentation of this file.
1/*
2 * Copyright 2019 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#ifndef skgpu_AsyncReadTypes_DEFINED
8#define skgpu_AsyncReadTypes_DEFINED
9
10#include "include/core/SkData.h"
13#include "include/core/SkSize.h"
18
19#include <cstddef>
20#include <forward_list>
21#include <utility>
22
23namespace skgpu {
24/**
25 * We sometimes hand clients objects that contain mapped buffers. The client may consume
26 * the mapped buffer on another thread. This object manages receiving messages that buffers are
27 * ready to be unmapped (on the owner's thread). It also handles cleaning up mapped
28 * buffers if the owner is destroyed before the client has finished with the buffer.
29 *
30 * Buffers are first registered using insert() before being passed the client. process() should be
31 * called periodically on the owner's thread to poll for messages and process them.
32 */
33template <typename T, typename IDType>
35public:
36 /**
37 * The message type that internal users of this should post to unmap the buffer.
38 * Set fInboxID to inboxID(). fBuffer must have been previously passed to insert().
39 */
42 IDType intendedRecipient)
43 : fBuffer(std::move(buffer)), fIntendedRecipient(intendedRecipient) {}
45 fBuffer = std::move(other.fBuffer);
46 fIntendedRecipient = other.fIntendedRecipient;
47 other.fIntendedRecipient.makeInvalid();
48 }
51 };
53 IDType,
54 false>;
55
57 : fFinishedBufferInbox(ownerID) {}
60
62 this->process();
63 if (!fAbandoned) {
64 // If we're going down before we got the messages we go ahead and unmap all the buffers.
65 // It's up to the client to ensure that they aren't being accessed on another thread
66 // while this is happening (or afterwards on any thread).
67 for (auto& b : fClientHeldBuffers) {
68 b->unmap();
69 }
70 }
71 }
72
75
76 /** Initialize BufferFinishedMessage::fIntendedRecipient to this value. It is the
77 * unique ID of the object that owns this buffer manager.
78 */
79 IDType ownerID() const {
80 return fFinishedBufferInbox.uniqueID();
81 }
82
83 /**
84 * Let the manager know to expect a message with buffer 'b'. It's illegal for a buffer to be
85 * inserted again before it is unmapped by process().
86 */
88 SkDEBUGCODE(auto end = fClientHeldBuffers.end());
89 SkASSERT(std::find(fClientHeldBuffers.begin(), end, b) == end);
90 fClientHeldBuffers.emplace_front(std::move(b));
91 }
92
93 /** Poll for messages and unmap any incoming buffers. */
94 void process() {
96 fFinishedBufferInbox.poll(&messages);
97 if (!fAbandoned) {
98 for (auto& m : messages) {
99 this->remove(m.fBuffer);
100 m.fBuffer->unmap();
101 }
102 }
103 }
104
105 /** Notifies the manager that the context has been abandoned. No more unmaps() will occur.*/
106 void abandon() {
107 fAbandoned = true;
108 fClientHeldBuffers.clear();
109 }
110
111private:
112 typename BufferFinishedMessageBus::Inbox fFinishedBufferInbox;
113 std::forward_list<sk_sp<T>> fClientHeldBuffers;
114 bool fAbandoned = false;
115
116 void remove(const sk_sp<T>& b) {
117 // There is no convenient remove only the first element that equals a value functionality in
118 // std::forward_list.
119 auto prev = fClientHeldBuffers.before_begin();
120 auto end = fClientHeldBuffers.end();
121 SkASSERT(std::find(fClientHeldBuffers.begin(), end, b) != end);
122 for (auto cur = fClientHeldBuffers.begin(); cur != end; prev = cur++) {
123 if (*cur == b) {
124 fClientHeldBuffers.erase_after(prev);
125 break;
126 }
127 }
128 SkASSERT(std::find(fClientHeldBuffers.begin(), end, b) == end);
129 }
130};
131
132////////////////////////////////////////////////////////////////////////////////
133
134template <typename T, typename IDType, typename TransferResultType>
136public:
137 TAsyncReadResult(IDType intendedRecipient)
138 : fIntendedRecipient(intendedRecipient) {
139 }
140
141 ~TAsyncReadResult() override {
142 for (int i = 0; i < fPlanes.size(); ++i) {
143 fPlanes[i].releaseMappedBuffer(fIntendedRecipient);
144 }
145 }
146
147 int count() const override { return fPlanes.size(); }
148 const void* data(int i) const override { return fPlanes[i].data(); }
149 size_t rowBytes(int i) const override { return fPlanes[i].rowBytes(); }
150
151 bool addTransferResult(const TransferResultType& result,
152 SkISize dimensions,
153 size_t rowBytes,
155 const void* mappedData = result.fTransferBuffer->map();
156 if (!mappedData) {
157 return false;
158 }
159 if (result.fPixelConverter) {
160 size_t size = rowBytes*dimensions.height();
162 result.fPixelConverter(data->writable_data(), mappedData);
163 this->addCpuPlane(std::move(data), rowBytes);
164 result.fTransferBuffer->unmap();
165 } else {
166 manager->insert(result.fTransferBuffer);
167 this->addMappedPlane(mappedData, rowBytes, std::move(result.fTransferBuffer));
168 }
169 return true;
170 }
171
173 SkASSERT(data);
174 SkASSERT(rowBytes > 0);
175 fPlanes.emplace_back(std::move(data), rowBytes);
176 }
177
178private:
179 void addMappedPlane(const void* data, size_t rowBytes, sk_sp<T> mappedBuffer) {
180 SkASSERT(data);
181 SkASSERT(rowBytes > 0);
182 SkASSERT(mappedBuffer);
183 SkASSERT(mappedBuffer->isMapped());
184 fPlanes.emplace_back(std::move(mappedBuffer), rowBytes);
185 }
186
187 class Plane {
188 public:
189 Plane(sk_sp<T> buffer, size_t rowBytes)
190 : fMappedBuffer(std::move(buffer)), fRowBytes(rowBytes) {}
191 Plane(sk_sp<SkData> data, size_t rowBytes) : fData(std::move(data)), fRowBytes(rowBytes) {}
192
193 Plane(Plane&&) = default;
194
195 ~Plane() { SkASSERT(!fMappedBuffer); }
196
197 Plane& operator=(const Plane&) = delete;
198 Plane& operator=(Plane&&) = default;
199
200 void releaseMappedBuffer(IDType intendedRecipient) {
201 if (fMappedBuffer) {
203 {std::move(fMappedBuffer), intendedRecipient});
204 }
205 }
206
207 const void* data() const {
208 if (fMappedBuffer) {
209 SkASSERT(!fData);
210 SkASSERT(fMappedBuffer->isMapped());
211 return fMappedBuffer->map();
212 }
213 SkASSERT(fData);
214 return fData->data();
215 }
216
217 size_t rowBytes() const { return fRowBytes; }
218
219 private:
220 sk_sp<SkData> fData;
221 sk_sp<T> fMappedBuffer;
222 size_t fRowBytes;
223 };
225 IDType fIntendedRecipient;
226};
227
228} // namespace skgpu
229
230#endif // skgpu_AsyncReadTypes_DEFINED
231
static float prev(float f)
#define SkASSERT(cond)
Definition SkAssert.h:116
#define SkDEBUGCODE(...)
Definition SkDebug.h:23
static sk_sp< SkData > MakeUninitialized(size_t length)
Definition SkData.cpp:116
void poll(skia_private::TArray< Message > *out)
IDType uniqueID() const
static void Post(Message m)
TAsyncReadResult(IDType intendedRecipient)
bool addTransferResult(const TransferResultType &result, SkISize dimensions, size_t rowBytes, TClientMappedBufferManager< T, IDType > *manager)
const void * data(int i) const override
size_t rowBytes(int i) const override
int count() const override
void addCpuPlane(sk_sp< SkData > data, size_t rowBytes)
TClientMappedBufferManager & operator=(const TClientMappedBufferManager &)=delete
TClientMappedBufferManager(TClientMappedBufferManager &&)=delete
TClientMappedBufferManager(const TClientMappedBufferManager &)=delete
TClientMappedBufferManager & operator=(TClientMappedBufferManager &&)=delete
int size() const
Definition SkTArray.h:416
T & emplace_back(Args &&... args)
Definition SkTArray.h:243
static bool b
glong glong end
static const uint8_t buffer[]
GAsyncResult * result
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
Definition switches.h:41
Definition ref_ptr.h:256
constexpr int32_t height() const
Definition SkSize.h:37
BufferFinishedMessage(sk_sp< T > buffer, IDType intendedRecipient)