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" 11 #include "include/core/SkImage.h" 12 #include "include/core/SkRefCnt.h" 13 #include "include/core/SkSize.h" 14 #include "include/private/base/SkAssert.h" 15 #include "include/private/base/SkDebug.h" 16 #include "include/private/base/SkTArray.h" 17 #include "src/core/SkMessageBus.h" 18 19 #include <cstddef> 20 #include <forward_list> 21 #include <utility> 22 23 namespace 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 */ 33 template <typename T, typename IDType> 34 class TClientMappedBufferManager { 35 public: 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 */ 40 struct BufferFinishedMessage { BufferFinishedMessageBufferFinishedMessage41 BufferFinishedMessage(sk_sp<T> buffer, 42 IDType intendedRecipient) 43 : fBuffer(std::move(buffer)), fIntendedRecipient(intendedRecipient) {} BufferFinishedMessageBufferFinishedMessage44 BufferFinishedMessage(BufferFinishedMessage&& other) { 45 fBuffer = std::move(other.fBuffer); 46 fIntendedRecipient = other.fIntendedRecipient; 47 other.fIntendedRecipient.makeInvalid(); 48 } 49 sk_sp<T> fBuffer; 50 IDType fIntendedRecipient; 51 }; 52 using BufferFinishedMessageBus = SkMessageBus<BufferFinishedMessage, 53 IDType, 54 false>; 55 TClientMappedBufferManager(IDType ownerID)56 TClientMappedBufferManager(IDType ownerID) 57 : fFinishedBufferInbox(ownerID) {} 58 TClientMappedBufferManager(const TClientMappedBufferManager&) = delete; 59 TClientMappedBufferManager(TClientMappedBufferManager&&) = delete; 60 ~TClientMappedBufferManager()61 ~TClientMappedBufferManager() { 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 73 TClientMappedBufferManager& operator=(const TClientMappedBufferManager&) = delete; 74 TClientMappedBufferManager& operator=(TClientMappedBufferManager&&) = delete; 75 76 /** Initialize BufferFinishedMessage::fIntendedRecipient to this value. It is the 77 * unique ID of the object that owns this buffer manager. 78 */ ownerID()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 */ insert(sk_sp<T> b)87 void insert(sk_sp<T> b) { 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. */ process()94 void process() { 95 skia_private::STArray<4, BufferFinishedMessage> messages; 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.*/ abandon()106 void abandon() { 107 fAbandoned = true; 108 fClientHeldBuffers.clear(); 109 } 110 111 private: 112 typename BufferFinishedMessageBus::Inbox fFinishedBufferInbox; 113 std::forward_list<sk_sp<T>> fClientHeldBuffers; 114 bool fAbandoned = false; 115 remove(const sk_sp<T> & b)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 134 template <typename T, typename IDType, typename TransferResultType> 135 class TAsyncReadResult : public SkImage::AsyncReadResult { 136 public: TAsyncReadResult(IDType intendedRecipient)137 TAsyncReadResult(IDType intendedRecipient) 138 : fIntendedRecipient(intendedRecipient) { 139 } 140 ~TAsyncReadResult()141 ~TAsyncReadResult() override { 142 for (int i = 0; i < fPlanes.size(); ++i) { 143 fPlanes[i].releaseMappedBuffer(fIntendedRecipient); 144 } 145 } 146 count()147 int count() const override { return fPlanes.size(); } data(int i)148 const void* data(int i) const override { return fPlanes[i].data(); } rowBytes(int i)149 size_t rowBytes(int i) const override { return fPlanes[i].rowBytes(); } 150 addTransferResult(const TransferResultType & result,SkISize dimensions,size_t rowBytes,TClientMappedBufferManager<T,IDType> * manager)151 bool addTransferResult(const TransferResultType& result, 152 SkISize dimensions, 153 size_t rowBytes, 154 TClientMappedBufferManager<T, IDType>* manager) { 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(); 161 sk_sp<SkData> data = SkData::MakeUninitialized(size); 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 addCpuPlane(sk_sp<SkData> data,size_t rowBytes)172 void addCpuPlane(sk_sp<SkData> data, size_t rowBytes) { 173 SkASSERT(data); 174 SkASSERT(rowBytes > 0); 175 fPlanes.emplace_back(std::move(data), rowBytes); 176 } 177 178 private: addMappedPlane(const void * data,size_t rowBytes,sk_sp<T> mappedBuffer)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: Plane(sk_sp<T> buffer,size_t rowBytes)189 Plane(sk_sp<T> buffer, size_t rowBytes) 190 : fMappedBuffer(std::move(buffer)), fRowBytes(rowBytes) {} Plane(sk_sp<SkData> data,size_t rowBytes)191 Plane(sk_sp<SkData> data, size_t rowBytes) : fData(std::move(data)), fRowBytes(rowBytes) {} 192 193 Plane(Plane&&) = default; 194 ~Plane()195 ~Plane() { SkASSERT(!fMappedBuffer); } 196 197 Plane& operator=(const Plane&) = delete; 198 Plane& operator=(Plane&&) = default; 199 releaseMappedBuffer(IDType intendedRecipient)200 void releaseMappedBuffer(IDType intendedRecipient) { 201 if (fMappedBuffer) { 202 TClientMappedBufferManager<T, IDType>::BufferFinishedMessageBus::Post( 203 {std::move(fMappedBuffer), intendedRecipient}); 204 } 205 } 206 data()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 rowBytes()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 }; 224 skia_private::STArray<4, Plane> fPlanes; 225 IDType fIntendedRecipient; 226 }; 227 228 } // namespace skgpu 229 230 #endif // skgpu_AsyncReadTypes_DEFINED 231 232