blob: a77e5982c040354dfc70cda56a389ac9088ea50f [file] [log] [blame]
/*
* Copyright 2019 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrClientMappedBufferManager_DEFINED
#define GrClientMappedBufferManager_DEFINED
#include "include/gpu/GrDirectContext.h"
#include "include/private/SkTArray.h"
#include "src/core/SkMessageBus.h"
#include "src/gpu/GrGpuBuffer.h"
#include <forward_list>
/**
* We sometimes hand clients objects that contain mapped GrGpuBuffers. The client may consume
* the mapped buffer on another thread. This object manages receiving messages that buffers are
* ready to be unmapped (on the GrDirectContext's thread). It also handles cleaning up mapped
* buffers if the GrDirectContext is destroyed before the client has finished with the buffer.
*
* Buffers are first registered using insert() before being passed the client. process() should be
* called periodically on the GrDirectContext thread to poll for messages and process them.
*/
class GrClientMappedBufferManager final {
public:
/**
* The message type that internal users of this should post to unmap the buffer.
* Set fInboxID to inboxID(). fBuffer must have been previously passed to insert().
*/
struct BufferFinishedMessage {
BufferFinishedMessage(sk_sp<GrGpuBuffer> buffer,
GrDirectContext::DirectContextID intendedRecipient)
: fBuffer(std::move(buffer)), fIntendedRecipient(intendedRecipient) {}
BufferFinishedMessage(BufferFinishedMessage&& other) {
fBuffer = std::move(other.fBuffer);
fIntendedRecipient = other.fIntendedRecipient;
other.fIntendedRecipient.makeInvalid();
}
sk_sp<GrGpuBuffer> fBuffer;
GrDirectContext::DirectContextID fIntendedRecipient;
};
using BufferFinishedMessageBus = SkMessageBus<BufferFinishedMessage,
GrDirectContext::DirectContextID,
false>;
GrClientMappedBufferManager(GrDirectContext::DirectContextID owningDirectContext);
GrClientMappedBufferManager(const GrClientMappedBufferManager&) = delete;
GrClientMappedBufferManager(GrClientMappedBufferManager&&) = delete;
~GrClientMappedBufferManager();
GrClientMappedBufferManager& operator=(const GrClientMappedBufferManager&) = delete;
GrClientMappedBufferManager& operator=(GrClientMappedBufferManager&&) = delete;
/** Initialize BufferFinishedMessage::fIntendedRecipient to this value. It is the
* unique ID of the GrDirectContext that owns this buffer manager.
*/
GrDirectContext::DirectContextID owningDirectContext() const {
return fFinishedBufferInbox.uniqueID();
}
/**
* Let the manager know to expect a message with buffer 'b'. It's illegal for a buffer to be
* inserted again before it is unmapped by process().
*/
void insert(sk_sp<GrGpuBuffer> b);
/** Poll for messages and unmap any incoming buffers. */
void process();
/** Notifies the manager that the context has been abandoned. No more unmaps() will occur.*/
void abandon();
private:
BufferFinishedMessageBus::Inbox fFinishedBufferInbox;
std::forward_list<sk_sp<GrGpuBuffer>> fClientHeldBuffers;
bool fAbandoned = false;
void remove(const sk_sp<GrGpuBuffer>& b);
};
bool SkShouldPostMessageToBus(const GrClientMappedBufferManager::BufferFinishedMessage&,
GrDirectContext::DirectContextID potentialRecipient);
#endif