зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1730282 - Cleanup IPC WebGL code. r=gfx-reviewers,lsalzman
* Replace QueueStatus with bool * Remove unused structs and code * Add some MOZ_LIKELY to (de)serialization branches Differential Revision: https://phabricator.services.mozilla.com/D125295
This commit is contained in:
Родитель
ebdc13da8f
Коммит
67e6fce4dd
|
@ -27,6 +27,7 @@
|
|||
#include "mozilla/layers/WebRenderUserData.h"
|
||||
#include "mozilla/layers/WebRenderCanvasRenderer.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/ResultVariant.h"
|
||||
#include "mozilla/ScopeExit.h"
|
||||
#include "mozilla/StaticPrefs_webgl.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
#include "WebGLFramebuffer.h"
|
||||
#include "WebGLTypes.h"
|
||||
#include "WebGLCommandQueue.h"
|
||||
#include "IpdlQueue.h"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
|
|
@ -1,669 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=4 et :
|
||||
*/
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef IPDLQUEUE_H_
|
||||
#define IPDLQUEUE_H_ 1
|
||||
|
||||
#include <atomic>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include "ipc/IPCMessageUtilsSpecializations.h"
|
||||
#include "mozilla/dom/QueueParamTraits.h"
|
||||
#include "mozilla/ipc/SharedMemoryBasic.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/ipc/Shmem.h"
|
||||
#include "mozilla/ipc/ProtocolUtils.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "mozilla/ScopeExit.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "mozilla/TypeTraits.h"
|
||||
#include "nsString.h"
|
||||
#include "mozilla/WeakPtr.h"
|
||||
|
||||
namespace IPC {
|
||||
template <typename T>
|
||||
struct ParamTraits;
|
||||
} // namespace IPC
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
using mozilla::webgl::QueueStatus;
|
||||
|
||||
extern LazyLogModule gIpdlQueueLog;
|
||||
#define IPDLQUEUE_LOG_(lvl, ...) \
|
||||
MOZ_LOG(mozilla::dom::gIpdlQueueLog, lvl, (__VA_ARGS__))
|
||||
#define IPDLQUEUE_LOGD(...) IPDLQUEUE_LOG_(LogLevel::Debug, __VA_ARGS__)
|
||||
#define IPDLQUEUE_LOGE(...) IPDLQUEUE_LOG_(LogLevel::Error, __VA_ARGS__)
|
||||
|
||||
template <typename ActorP, typename ActorC>
|
||||
class IpdlQueue;
|
||||
template <typename Derived>
|
||||
class SyncConsumerActor;
|
||||
|
||||
enum IpdlQueueProtocol {
|
||||
/**
|
||||
* Sends the message immediately. Does not wait for a response.
|
||||
*/
|
||||
kAsync,
|
||||
/**
|
||||
* Sends the message immediately or caches it for a later batch
|
||||
* send. Messages may be sent at any point in the future but
|
||||
* will always be processed in order. kSync messages always force
|
||||
* a flush of the cache but other mechanisms (e.g. periodic tasks)
|
||||
* can do this as well.
|
||||
*/
|
||||
kBufferedAsync,
|
||||
/**
|
||||
* Sends the message immediately. Waits for any response message,
|
||||
* which can immediately be read upon completion of the send.
|
||||
*/
|
||||
kSync
|
||||
};
|
||||
|
||||
constexpr uint64_t kIllegalQueueId = 0;
|
||||
inline uint64_t NewIpdlQueueId() {
|
||||
static std::atomic<uint64_t> sNextIpdlQueueId = 1;
|
||||
return sNextIpdlQueueId++;
|
||||
}
|
||||
|
||||
struct IpdlQueueBuffer {
|
||||
uint64_t id = kIllegalQueueId;
|
||||
nsTArray<uint8_t> data;
|
||||
|
||||
IpdlQueueBuffer() = default;
|
||||
IpdlQueueBuffer(const IpdlQueueBuffer&) = delete;
|
||||
IpdlQueueBuffer(IpdlQueueBuffer&&) = default;
|
||||
IpdlQueueBuffer(uint64_t aId, nsTArray<uint8_t>&& aData)
|
||||
: id(aId), data(std::move(aData)) {}
|
||||
};
|
||||
|
||||
using IpdlQueueBuffers = nsTArray<IpdlQueueBuffer>;
|
||||
|
||||
static constexpr uint32_t kAsyncFlushWaitMs = 4; // 4ms
|
||||
|
||||
template <typename Derived>
|
||||
class AsyncProducerActor {
|
||||
public:
|
||||
virtual bool TransmitIpdlQueueData(IpdlQueueProtocol aProtocol,
|
||||
IpdlQueueBuffer&& aData) {
|
||||
MOZ_ASSERT((aProtocol == IpdlQueueProtocol::kAsync) ||
|
||||
(aProtocol == IpdlQueueProtocol::kBufferedAsync));
|
||||
|
||||
if (mResponseBuffers || (aProtocol == IpdlQueueProtocol::kBufferedAsync)) {
|
||||
// Always use response buffer if set.
|
||||
auto& buffers = mResponseBuffers ? *mResponseBuffers : mAsyncBuffers;
|
||||
|
||||
// We are in the middle of a sync transaction. Store the data so
|
||||
// that we can return it with the response.
|
||||
const uint64_t id = aData.id;
|
||||
for (auto& elt : buffers) {
|
||||
if (elt.id == id) {
|
||||
elt.data.AppendElements(aData.data);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
buffers.AppendElement(std::move(aData));
|
||||
|
||||
if (!mResponseBuffers) {
|
||||
PostFlushAsyncCache(kAsyncFlushWaitMs);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// We are not inside of a transaction. Send normally, but first send any
|
||||
// cached messages.
|
||||
FlushAsyncCache();
|
||||
|
||||
Derived* self = static_cast<Derived*>(this);
|
||||
return self->SendTransmitIpdlQueueData(std::move(aData));
|
||||
}
|
||||
|
||||
// This can be called at any time to flush all queued async messages.
|
||||
bool FlushAsyncCache() {
|
||||
Derived* self = static_cast<Derived*>(this);
|
||||
for (auto& elt : mAsyncBuffers) {
|
||||
if (!elt.data.IsEmpty()) {
|
||||
if (!self->SendTransmitIpdlQueueData(std::move(elt))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
mAsyncBuffers.Clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PostFlushAsyncCache(uint32_t aEstWaitTimeMs) {
|
||||
if (mPostedFlushRunnable) {
|
||||
// Already scheduled a flush for later.
|
||||
return true;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(GetCurrentSerialEventTarget(),
|
||||
"No message loop for IpdlQueue flush task");
|
||||
|
||||
Derived* self = static_cast<Derived*>(this);
|
||||
// IpdlProducer/IpdlConsumer guarantees the actor supports WeakPtr.
|
||||
auto weak = WeakPtr<Derived>(self);
|
||||
already_AddRefed<mozilla::Runnable> flushRunnable =
|
||||
NS_NewRunnableFunction("FlushAsyncCache", [weak] {
|
||||
auto strong = RefPtr<Derived>(weak);
|
||||
if (!strong) {
|
||||
return;
|
||||
}
|
||||
strong->FlushAsyncCache();
|
||||
strong->ClearFlushRunnable();
|
||||
});
|
||||
|
||||
NS_ENSURE_SUCCESS(GetCurrentSerialEventTarget()->DelayedDispatch(
|
||||
std::move(flushRunnable), aEstWaitTimeMs),
|
||||
false);
|
||||
mPostedFlushRunnable = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void ClearFlushRunnable() { mPostedFlushRunnable = false; }
|
||||
|
||||
template <typename... Args>
|
||||
IpdlQueueProtocol GetIpdlQueueProtocol(const Args&...) {
|
||||
return IpdlQueueProtocol::kAsync;
|
||||
}
|
||||
|
||||
protected:
|
||||
friend SyncConsumerActor<Derived>;
|
||||
|
||||
void SetResponseBuffers(IpdlQueueBuffers* aResponse) {
|
||||
MOZ_ASSERT(!mResponseBuffers);
|
||||
mResponseBuffers = aResponse;
|
||||
|
||||
// Response should include any cached async transmissions.
|
||||
*mResponseBuffers = std::move(mAsyncBuffers);
|
||||
}
|
||||
|
||||
void ClearResponseBuffers() {
|
||||
MOZ_ASSERT(mResponseBuffers);
|
||||
mResponseBuffers = nullptr;
|
||||
}
|
||||
|
||||
// Stores response when inside of a kSync transaction.
|
||||
IpdlQueueBuffers* mResponseBuffers = nullptr;
|
||||
// For kBufferedAsync transmissions that occur outside of a response to a
|
||||
// kSync message.
|
||||
IpdlQueueBuffers mAsyncBuffers;
|
||||
|
||||
bool mPostedFlushRunnable = false;
|
||||
};
|
||||
|
||||
template <typename Derived>
|
||||
class SyncProducerActor : public AsyncProducerActor<Derived> {
|
||||
public:
|
||||
bool TransmitIpdlQueueData(IpdlQueueProtocol aProtocol,
|
||||
IpdlQueueBuffer&& aData) override {
|
||||
Derived* self = static_cast<Derived*>(this);
|
||||
if (mResponseBuffers || (aProtocol != IpdlQueueProtocol::kSync)) {
|
||||
return AsyncProducerActor<Derived>::TransmitIpdlQueueData(
|
||||
aProtocol, std::forward<IpdlQueueBuffer>(aData));
|
||||
}
|
||||
|
||||
IpdlQueueBuffers responses;
|
||||
if (!self->SendExchangeIpdlQueueData(std::forward<IpdlQueueBuffer>(aData),
|
||||
&responses)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto& buf : responses) {
|
||||
if (!self->StoreIpdlQueueData(std::move(buf))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
using AsyncProducerActor<Derived>::mResponseBuffers;
|
||||
};
|
||||
|
||||
template <typename Derived>
|
||||
class AsyncConsumerActor {
|
||||
public:
|
||||
// Returns the ipdlQueue contents that were Recv'ed in a prior IPDL
|
||||
// transmission. No new data is received via IPDL during this operation.
|
||||
nsTArray<uint8_t> TakeIpdlQueueData(uint64_t aId) {
|
||||
auto it = mIpdlQueueBuffers.find(aId);
|
||||
if (it != mIpdlQueueBuffers.end()) {
|
||||
return std::move(it->second.data);
|
||||
}
|
||||
return nsTArray<uint8_t>();
|
||||
}
|
||||
|
||||
protected:
|
||||
friend SyncProducerActor<Derived>;
|
||||
|
||||
// Store data received from the producer, to be read by local IpdlConsumers.
|
||||
bool StoreIpdlQueueData(IpdlQueueBuffer&& aBuffer) {
|
||||
auto it = mIpdlQueueBuffers.find(aBuffer.id);
|
||||
if (it == mIpdlQueueBuffers.end()) {
|
||||
return mIpdlQueueBuffers.insert({aBuffer.id, std::move(aBuffer)}).second;
|
||||
}
|
||||
return it->second.data.AppendElements(aBuffer.data, fallible);
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult RecvTransmitIpdlQueueData(IpdlQueueBuffer&& aBuffer) {
|
||||
if (StoreIpdlQueueData(std::forward<IpdlQueueBuffer>(aBuffer))) {
|
||||
return IPC_OK();
|
||||
}
|
||||
return IPC_FAIL_NO_REASON(static_cast<Derived*>(this));
|
||||
}
|
||||
|
||||
std::unordered_map<uint64_t, IpdlQueueBuffer> mIpdlQueueBuffers;
|
||||
};
|
||||
|
||||
template <typename Derived>
|
||||
class SyncConsumerActor : public AsyncConsumerActor<Derived> {
|
||||
protected:
|
||||
using AsyncConsumerActor<Derived>::StoreIpdlQueueData;
|
||||
|
||||
mozilla::ipc::IPCResult RecvExchangeIpdlQueueData(
|
||||
IpdlQueueBuffer&& aBuffer, IpdlQueueBuffers* aResponse) {
|
||||
uint64_t id = aBuffer.id;
|
||||
if (!StoreIpdlQueueData(std::forward<IpdlQueueBuffer>(aBuffer))) {
|
||||
return IPC_FAIL_NO_REASON(static_cast<Derived*>(this));
|
||||
}
|
||||
|
||||
// Mark the actor as in a sync operation, then calls handler.
|
||||
// During handler, if actor is used as producer (for ALL queues)
|
||||
// then instead of immediately sending, it writes the data into
|
||||
// aResponse. When handler is done, we unmark the actor.
|
||||
// Note that we must buffer for _all_ queues associated with the
|
||||
// actor as the intended response queue is indistinguishable from
|
||||
// the rest from our vantage point.
|
||||
Derived* actor = static_cast<Derived*>(this);
|
||||
actor->SetResponseBuffers(aResponse);
|
||||
auto clearResponseBuffer =
|
||||
MakeScopeExit([&] { actor->ClearResponseBuffers(); });
|
||||
|
||||
#if defined(DEBUG)
|
||||
// Response now includes any cached async transmissions. It is
|
||||
// illegal to have a response queue also used for other purposes
|
||||
// so the cache for that queue must be empty.
|
||||
DebugOnly<bool> responseBufferIsEmpty = [&] {
|
||||
for (auto& elt : *aResponse) {
|
||||
if (elt.id == id) {
|
||||
return elt.data.IsEmpty();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}();
|
||||
MOZ_ASSERT(responseBufferIsEmpty);
|
||||
#endif
|
||||
|
||||
return actor->RunQueue(id) ? IPC_OK() : IPC_FAIL_NO_REASON(actor);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename _Actor>
|
||||
class IpdlProducer final : public SupportsWeakPtr {
|
||||
nsTArray<uint8_t> mSerializedData;
|
||||
WeakPtr<_Actor> mActor;
|
||||
uint64_t mId;
|
||||
|
||||
public:
|
||||
using Actor = _Actor;
|
||||
using SelfType = IpdlProducer<Actor>;
|
||||
|
||||
// For IPDL:
|
||||
IpdlProducer() : mId(kIllegalQueueId) {}
|
||||
|
||||
/**
|
||||
* Insert aArgs into the queue. If the operation does not succeed then
|
||||
* the queue is unchanged.
|
||||
*/
|
||||
template <typename... Args>
|
||||
QueueStatus TryInsert(Args&&... aArgs) {
|
||||
MOZ_ASSERT(mId != kIllegalQueueId);
|
||||
if (!mActor) {
|
||||
NS_WARNING("TryInsert with actor that was already freed.");
|
||||
return QueueStatus::kFatalError;
|
||||
}
|
||||
|
||||
// Fill mSerializedData with the data to send. Clear it when done.
|
||||
MOZ_ASSERT(mSerializedData.IsEmpty());
|
||||
auto self = *this;
|
||||
auto clearData = MakeScopeExit([&] { self.mSerializedData.Clear(); });
|
||||
const IpdlQueueProtocol protocol = mActor->GetIpdlQueueProtocol(aArgs...);
|
||||
QueueStatus status = SerializeAllArgs(std::forward<Args>(aArgs)...);
|
||||
if (status != QueueStatus::kSuccess) {
|
||||
return status;
|
||||
}
|
||||
return mActor->TransmitIpdlQueueData(
|
||||
protocol, IpdlQueueBuffer(mId, std::move(mSerializedData)))
|
||||
? QueueStatus::kSuccess
|
||||
: QueueStatus::kFatalError;
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as TryInsert. IPDL send failures are considered fatal to the
|
||||
* IpdlQueue.
|
||||
*/
|
||||
template <typename... Args>
|
||||
QueueStatus TryWaitInsert(const Maybe<TimeDuration>&, Args&&... aArgs) {
|
||||
return TryInsert(std::forward<Args>(aArgs)...);
|
||||
}
|
||||
|
||||
QueueStatus AllocShmem(mozilla::ipc::Shmem* aShmem, size_t aBufferSize,
|
||||
const void* aBuffer = nullptr) {
|
||||
if (!mActor) {
|
||||
return QueueStatus::kFatalError;
|
||||
}
|
||||
|
||||
if (!mActor->AllocShmem(
|
||||
aBufferSize,
|
||||
mozilla::ipc::SharedMemory::SharedMemoryType::TYPE_BASIC, aShmem)) {
|
||||
return QueueStatus::kOOMError;
|
||||
}
|
||||
|
||||
if (aBuffer) {
|
||||
memcpy(aShmem->get<uint8_t>(), aBuffer, aBufferSize);
|
||||
}
|
||||
return QueueStatus::kSuccess;
|
||||
}
|
||||
|
||||
protected:
|
||||
template <typename T1, typename T2>
|
||||
friend class IpdlQueue;
|
||||
friend struct mozilla::ipc::IPDLParamTraits<SelfType>;
|
||||
|
||||
explicit IpdlProducer(uint64_t aId, Actor* aActor = nullptr)
|
||||
: mActor(aActor), mId(aId) {}
|
||||
|
||||
template <typename... Args>
|
||||
QueueStatus SerializeAllArgs(Args&&... aArgs) {
|
||||
size_t read = 0;
|
||||
size_t write = 0;
|
||||
mozilla::webgl::ProducerView<SelfType> view(this, read, &write);
|
||||
size_t bytesNeeded = MinSizeofArgs(view, aArgs...);
|
||||
if (!mSerializedData.SetLength(bytesNeeded, fallible)) {
|
||||
return QueueStatus::kOOMError;
|
||||
}
|
||||
|
||||
return SerializeArgs(view, aArgs...);
|
||||
}
|
||||
|
||||
QueueStatus SerializeArgs(mozilla::webgl::ProducerView<SelfType>& aView) {
|
||||
return QueueStatus::kSuccess;
|
||||
}
|
||||
|
||||
template <typename Arg, typename... Args>
|
||||
QueueStatus SerializeArgs(mozilla::webgl::ProducerView<SelfType>& aView,
|
||||
const Arg& aArg, const Args&... aArgs) {
|
||||
QueueStatus status = SerializeArg(aView, aArg);
|
||||
if (!IsSuccess(status)) {
|
||||
return status;
|
||||
}
|
||||
return SerializeArgs(aView, aArgs...);
|
||||
}
|
||||
|
||||
template <typename Arg>
|
||||
QueueStatus SerializeArg(mozilla::webgl::ProducerView<SelfType>& aView,
|
||||
const Arg& aArg) {
|
||||
return mozilla::webgl::QueueParamTraits<
|
||||
typename std::remove_volatile<Arg>::type>::Write(aView, aArg);
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename Arg>
|
||||
QueueStatus WriteObject(size_t aRead, size_t* aWrite, const Arg& arg,
|
||||
size_t aArgSize) {
|
||||
if (mSerializedData.Length() < (*aWrite) + aArgSize) {
|
||||
// Previous MinSizeOfArgs estimate was insufficient. Resize the
|
||||
// buffer to accomodate our real needs.
|
||||
mSerializedData.SetLength(*aWrite + aArgSize);
|
||||
}
|
||||
return mozilla::webgl::Marshaller::WriteObject(
|
||||
mSerializedData.Elements(), mSerializedData.Length() + 1, aRead, aWrite,
|
||||
arg, aArgSize);
|
||||
}
|
||||
|
||||
base::ProcessId OtherPid() { return mActor ? mActor->OtherPid() : 0; }
|
||||
|
||||
protected:
|
||||
size_t MinSizeofArgs(mozilla::webgl::ProducerView<SelfType>& aView) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename Arg, typename... Args>
|
||||
size_t MinSizeofArgs(mozilla::webgl::ProducerView<SelfType>& aView,
|
||||
const Arg& aArg, const Args&... aArgs) {
|
||||
return aView.MinSizeParam(aArg) + MinSizeofArgs(aView, aArgs...);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename _Actor>
|
||||
class IpdlConsumer final : public SupportsWeakPtr {
|
||||
public:
|
||||
using Actor = _Actor;
|
||||
using SelfType = IpdlConsumer<Actor>;
|
||||
|
||||
// For IPDL
|
||||
IpdlConsumer() : mId(kIllegalQueueId) {}
|
||||
|
||||
/**
|
||||
* Attempts to copy and remove aArgs from the queue. If the operation does
|
||||
* not succeed then the queue is unchanged. If the operation returns
|
||||
* kQueueNotReady then the consumer does not yet have enough data to satisfy
|
||||
* the request. In this case, the IPDL MessageQueue should be given the
|
||||
* opportunity to run, at which point TryRemove can be attempted again.
|
||||
*/
|
||||
template <typename... Args>
|
||||
QueueStatus TryRemove(Args&... aArgs) {
|
||||
MOZ_ASSERT(mId != kIllegalQueueId);
|
||||
if (!mActor) {
|
||||
NS_WARNING("TryRemove with actor that was already freed.");
|
||||
return QueueStatus::kFatalError;
|
||||
}
|
||||
mBuf.AppendElements(mActor->TakeIpdlQueueData(mId));
|
||||
return DeserializeAllArgs(aArgs...);
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalent to TryRemove. Duration is ignored as it would need to
|
||||
* allow the IPDL queue to run to be useful.
|
||||
*/
|
||||
template <typename... Args>
|
||||
QueueStatus TryWaitRemove(const Maybe<TimeDuration>&, Args&... aArgs) {
|
||||
return TryRemove(aArgs...);
|
||||
}
|
||||
|
||||
mozilla::ipc::Shmem::SharedMemory* LookupSharedMemory(uint32_t aId) {
|
||||
return mActor ? mActor->LookupSharedMemory(aId) : nullptr;
|
||||
}
|
||||
|
||||
protected:
|
||||
template <typename T1, typename T2>
|
||||
friend class IpdlQueue;
|
||||
friend struct mozilla::ipc::IPDLParamTraits<SelfType>;
|
||||
|
||||
explicit IpdlConsumer(uint64_t aId, Actor* aActor = nullptr)
|
||||
: mActor(aActor), mId(aId) {}
|
||||
|
||||
template <typename... Args>
|
||||
QueueStatus DeserializeAllArgs(Args&... aArgs) {
|
||||
size_t read = 0;
|
||||
size_t write = mBuf.Length();
|
||||
mozilla::webgl::ConsumerView<SelfType> view(this, &read, write);
|
||||
|
||||
QueueStatus status = DeserializeArgs(view, aArgs...);
|
||||
if (IsSuccess(status) && (read > 0)) {
|
||||
mBuf.RemoveElementsAt(0, read);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
QueueStatus DeserializeArgs(mozilla::webgl::ConsumerView<SelfType>& aView) {
|
||||
return QueueStatus::kSuccess;
|
||||
}
|
||||
|
||||
template <typename Arg, typename... Args>
|
||||
QueueStatus DeserializeArgs(mozilla::webgl::ConsumerView<SelfType>& aView,
|
||||
Arg& aArg, Args&... aArgs) {
|
||||
QueueStatus status = DeserializeArg(aView, aArg);
|
||||
if (!IsSuccess(status)) {
|
||||
return status;
|
||||
}
|
||||
return DeserializeArgs(aView, aArgs...);
|
||||
}
|
||||
|
||||
template <typename Arg>
|
||||
QueueStatus DeserializeArg(mozilla::webgl::ConsumerView<SelfType>& aView,
|
||||
Arg& aArg) {
|
||||
return mozilla::webgl::
|
||||
QueueParamTraits<typename mozilla::webgl::RemoveCVR<Arg>::Type>::Read(
|
||||
aView, const_cast<std::remove_cv_t<Arg>*>(&aArg));
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename Arg>
|
||||
QueueStatus ReadObject(size_t* aRead, size_t aWrite, Arg* arg,
|
||||
size_t aArgSize) {
|
||||
// TODO: Queue needs one extra byte for PCQ (fixme).
|
||||
return mozilla::webgl::Marshaller::ReadObject(
|
||||
mBuf.Elements(), mBuf.Length() + 1, aRead, aWrite, arg, aArgSize);
|
||||
}
|
||||
|
||||
base::ProcessId OtherPid() { return mActor ? mActor->OtherPid() : 0; }
|
||||
|
||||
protected:
|
||||
WeakPtr<Actor> mActor;
|
||||
uint64_t mId;
|
||||
nsTArray<uint8_t> mBuf;
|
||||
};
|
||||
|
||||
/**
|
||||
* An IpdlQueue is a queue that uses an actor of type ActorP to send data and
|
||||
* its reciprocal (i.e. child to its parent or vice-versa) to receive data.
|
||||
* ActorP must derive from one of:
|
||||
* AsyncProducerActor, SyncProducerActor
|
||||
* ActorC must derive from one of:
|
||||
* AsyncConsumerActor, SyncConsumerActor
|
||||
*/
|
||||
template <typename _ActorP, typename _ActorC>
|
||||
class IpdlQueue final {
|
||||
public:
|
||||
using ActorP = _ActorP;
|
||||
using ActorC = _ActorC;
|
||||
using Producer = IpdlProducer<ActorP>;
|
||||
using Consumer = IpdlConsumer<ActorC>;
|
||||
|
||||
UniquePtr<Producer> TakeProducer() { return std::move(mProducer); }
|
||||
UniquePtr<Consumer> TakeConsumer() { return std::move(mConsumer); }
|
||||
|
||||
/**
|
||||
* Create an IpdlQueue where the given actor is a producer and its
|
||||
* reciprocal is the consumer.
|
||||
* The reciprocal actor type must be typedefed in ActorC as OtherSideActor.
|
||||
* For example, WebGLChild::OtherSideActor is WebGLParent.
|
||||
*/
|
||||
static UniquePtr<IpdlQueue<ActorP, ActorC>> Create(ActorP* aProducerActor) {
|
||||
static_assert(std::is_same<typename ActorP::OtherSideActor, ActorC>::value,
|
||||
"ActorP's reciprocal must be ActorC");
|
||||
static_assert(std::is_same<typename ActorC::OtherSideActor, ActorP>::value,
|
||||
"ActorC's reciprocal must be ActorP");
|
||||
|
||||
auto id = NewIpdlQueueId();
|
||||
return WrapUnique(new IpdlQueue<ActorP, ActorC>(
|
||||
std::move(WrapUnique(new Producer(id, aProducerActor))),
|
||||
std::move(WrapUnique(new Consumer(id)))));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an IpdlQueue where the given actor is a consumer and its
|
||||
* reciprocal is the producer.
|
||||
* The reciprocal actor type must be typedefed in ActorC as OtherSideActor.
|
||||
* For example, WebGLChild::OtherSideActor is WebGLParent.
|
||||
*/
|
||||
static UniquePtr<IpdlQueue<ActorP, ActorC>> Create(ActorC* aConsumerActor) {
|
||||
static_assert(std::is_same<typename ActorP::OtherSideActor, ActorC>::value,
|
||||
"ActorP's reciprocal must be ActorC");
|
||||
static_assert(std::is_same<typename ActorC::OtherSideActor, ActorP>::value,
|
||||
"ActorC's reciprocal must be ActorP");
|
||||
|
||||
auto id = NewIpdlQueueId();
|
||||
return WrapUnique(new IpdlQueue<ActorP, ActorC>(
|
||||
std::move(WrapUnique(new Producer(id))),
|
||||
std::move(WrapUnique(new Consumer(id, aConsumerActor)))));
|
||||
}
|
||||
|
||||
private:
|
||||
IpdlQueue(UniquePtr<Producer>&& aProducer, UniquePtr<Consumer>&& aConsumer)
|
||||
: mProducer(std::move(aProducer)), mConsumer(std::move(aConsumer)) {}
|
||||
|
||||
UniquePtr<Producer> mProducer;
|
||||
UniquePtr<Consumer> mConsumer;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
||||
namespace ipc {
|
||||
|
||||
template <typename Actor>
|
||||
struct IPDLParamTraits<mozilla::dom::IpdlProducer<Actor>> {
|
||||
using paramType = mozilla::dom::IpdlProducer<Actor>;
|
||||
|
||||
static void Write(IPC::Message* aMsg, IProtocol* aActor,
|
||||
const paramType& aParam) {
|
||||
MOZ_ASSERT(aParam.mActor == nullptr);
|
||||
WriteIPDLParam(aMsg, aActor, aParam.mId);
|
||||
}
|
||||
|
||||
static bool Read(const IPC::Message* aMsg, PickleIterator* aIter,
|
||||
IProtocol* aActor, paramType* aResult) {
|
||||
aResult->mActor = static_cast<Actor*>(aActor);
|
||||
return ReadIPDLParam(aMsg, aIter, aActor, &aResult->mId);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Actor>
|
||||
struct IPDLParamTraits<mozilla::dom::IpdlConsumer<Actor>> {
|
||||
using paramType = mozilla::dom::IpdlConsumer<Actor>;
|
||||
|
||||
static void Write(IPC::Message* aMsg, IProtocol* aActor,
|
||||
const paramType& aParam) {
|
||||
MOZ_ASSERT(aParam.mActor == nullptr);
|
||||
WriteIPDLParam(aMsg, aActor, aParam.mId);
|
||||
WriteIPDLParam(aMsg, aActor, aParam.mBuf);
|
||||
}
|
||||
|
||||
static bool Read(const IPC::Message* aMsg, PickleIterator* aIter,
|
||||
IProtocol* aActor, paramType* aResult) {
|
||||
aResult->mActor = static_cast<Actor*>(aActor);
|
||||
return ReadIPDLParam(aMsg, aIter, aActor, &aResult->mId) &&
|
||||
ReadIPDLParam(aMsg, aIter, aActor, &aResult->mBuf);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct IPDLParamTraits<mozilla::dom::IpdlQueueBuffer> {
|
||||
using paramType = mozilla::dom::IpdlQueueBuffer;
|
||||
|
||||
static void Write(IPC::Message* aMsg, IProtocol* aActor,
|
||||
const paramType& aParam) {
|
||||
WriteParam(aMsg, aParam.id);
|
||||
WriteParam(aMsg, aParam.data);
|
||||
}
|
||||
|
||||
static bool Read(const IPC::Message* aMsg, PickleIterator* aIter,
|
||||
IProtocol* aActor, paramType* aResult) {
|
||||
return ReadParam(aMsg, aIter, &aResult->id) &&
|
||||
ReadParam(aMsg, aIter, &aResult->data);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // IPDLQUEUE_H_
|
|
@ -24,8 +24,6 @@ using mozilla::webgl::ShaderPrecisionFormat from "mozilla/dom/WebGLIpdl.h";
|
|||
using mozilla::webgl::OpaqueFramebufferOptions from "mozilla/dom/WebGLIpdl.h";
|
||||
using mozilla::webgl::ReadPixelsDesc from "mozilla/dom/WebGLIpdl.h";
|
||||
using mozilla::webgl::ReadPixelsResultIpc from "mozilla/dom/WebGLIpdl.h";
|
||||
using mozilla::dom::IpdlQueueBuffer from "mozilla/dom/IpdlQueue.h";
|
||||
using mozilla::dom::IpdlQueueBuffers from "mozilla/dom/IpdlQueue.h";
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
|
|
@ -25,46 +25,12 @@
|
|||
namespace mozilla {
|
||||
namespace webgl {
|
||||
|
||||
enum class QueueStatus {
|
||||
// Operation was successful
|
||||
kSuccess,
|
||||
// The operation failed because the queue isn't ready for it.
|
||||
// Either the queue is too full for an insert or too empty for a remove.
|
||||
// The operation may succeed if retried.
|
||||
kNotReady,
|
||||
// The operation required more room than the queue supports.
|
||||
// It should not be retried -- it will always fail.
|
||||
kTooSmall,
|
||||
// The operation failed for some reason that is unrecoverable.
|
||||
// All values below this value indicate a fata error.
|
||||
kFatalError,
|
||||
// Fatal error: Internal processing ran out of memory. This is likely e.g.
|
||||
// during de-serialization.
|
||||
kOOMError,
|
||||
};
|
||||
|
||||
inline bool IsSuccess(QueueStatus status) {
|
||||
return status == QueueStatus::kSuccess;
|
||||
}
|
||||
|
||||
inline bool operator!(const QueueStatus status) { return !IsSuccess(status); }
|
||||
|
||||
template <typename T>
|
||||
struct RemoveCVR {
|
||||
using Type =
|
||||
typename std::remove_reference<typename std::remove_cv<T>::type>::type;
|
||||
};
|
||||
|
||||
inline size_t UsedBytes(size_t aQueueBufferSize, size_t aRead, size_t aWrite) {
|
||||
return (aRead <= aWrite) ? aWrite - aRead
|
||||
: (aQueueBufferSize - aRead) + aWrite;
|
||||
}
|
||||
|
||||
inline size_t FreeBytes(size_t aQueueBufferSize, size_t aRead, size_t aWrite) {
|
||||
// Remember, queueSize is queueBufferSize-1
|
||||
return (aQueueBufferSize - 1) - UsedBytes(aQueueBufferSize, aRead, aWrite);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct IsTriviallySerializable
|
||||
: public std::integral_constant<bool, std::is_arithmetic<T>::value &&
|
||||
|
@ -96,53 +62,6 @@ struct IsTriviallySerializable
|
|||
template <typename Arg>
|
||||
struct QueueParamTraits; // Todo: s/QueueParamTraits/SizedParamTraits/
|
||||
|
||||
/**
|
||||
* The marshaller handles all data insertion into the queue.
|
||||
*/
|
||||
class Marshaller {
|
||||
public:
|
||||
static QueueStatus WriteObject(uint8_t* aQueue, size_t aQueueBufferSize,
|
||||
size_t aRead, size_t* aWrite, const void* aArg,
|
||||
size_t aArgLength) {
|
||||
const uint8_t* buf = reinterpret_cast<const uint8_t*>(aArg);
|
||||
if (FreeBytes(aQueueBufferSize, aRead, *aWrite) < aArgLength) {
|
||||
return QueueStatus::kNotReady;
|
||||
}
|
||||
|
||||
if (*aWrite + aArgLength <= aQueueBufferSize) {
|
||||
memcpy(aQueue + *aWrite, buf, aArgLength);
|
||||
} else {
|
||||
size_t firstLen = aQueueBufferSize - *aWrite;
|
||||
memcpy(aQueue + *aWrite, buf, firstLen);
|
||||
memcpy(aQueue, &buf[firstLen], aArgLength - firstLen);
|
||||
}
|
||||
*aWrite = (*aWrite + aArgLength) % aQueueBufferSize;
|
||||
return QueueStatus::kSuccess;
|
||||
}
|
||||
|
||||
static QueueStatus ReadObject(const uint8_t* aQueue, size_t aQueueBufferSize,
|
||||
size_t* aRead, size_t aWrite, void* aArg,
|
||||
size_t aArgLength) {
|
||||
if (UsedBytes(aQueueBufferSize, *aRead, aWrite) < aArgLength) {
|
||||
return QueueStatus::kNotReady;
|
||||
}
|
||||
|
||||
if (aArg) {
|
||||
uint8_t* buf = reinterpret_cast<uint8_t*>(aArg);
|
||||
if (*aRead + aArgLength <= aQueueBufferSize) {
|
||||
memcpy(buf, aQueue + *aRead, aArgLength);
|
||||
} else {
|
||||
size_t firstLen = aQueueBufferSize - *aRead;
|
||||
memcpy(buf, aQueue + *aRead, firstLen);
|
||||
memcpy(&buf[firstLen], aQueue, aArgLength - firstLen);
|
||||
}
|
||||
}
|
||||
|
||||
*aRead = (*aRead + aArgLength) % aQueueBufferSize;
|
||||
return QueueStatus::kSuccess;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline Range<T> AsRange(T* const begin, T* const end) {
|
||||
const auto size = MaybeAs<size_t>(end - begin);
|
||||
|
@ -161,53 +80,48 @@ class ProducerView {
|
|||
public:
|
||||
using Producer = _Producer;
|
||||
|
||||
ProducerView(Producer* aProducer, size_t aRead, size_t* aWrite)
|
||||
: mProducer(aProducer),
|
||||
mRead(aRead),
|
||||
mWrite(aWrite),
|
||||
mStatus(QueueStatus::kSuccess) {}
|
||||
explicit ProducerView(Producer* aProducer)
|
||||
: mProducer(aProducer) {}
|
||||
|
||||
template <typename T>
|
||||
QueueStatus WriteFromRange(const Range<const T>& src) {
|
||||
if (!mStatus) return mStatus;
|
||||
mProducer->WriteFromRange(src);
|
||||
return mStatus;
|
||||
bool WriteFromRange(const Range<const T>& src) {
|
||||
if (MOZ_LIKELY(mOk)) {
|
||||
mOk &= mProducer->WriteFromRange(src);
|
||||
}
|
||||
return mOk;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy bytes from aBuffer to the producer if there is enough room.
|
||||
* aBufferSize must not be 0.
|
||||
*/
|
||||
template <typename T>
|
||||
inline QueueStatus Write(const T* begin, const T* end) {
|
||||
inline bool Write(const T* begin, const T* end) {
|
||||
MOZ_RELEASE_ASSERT(begin <= end);
|
||||
if (!mStatus) return mStatus;
|
||||
WriteFromRange(AsRange(begin, end));
|
||||
return mStatus;
|
||||
return WriteFromRange(AsRange(begin, end));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline QueueStatus WritePod(const T& in) {
|
||||
inline bool WritePod(const T& in) {
|
||||
static_assert(std::is_trivially_copyable_v<T>);
|
||||
const auto begin = reinterpret_cast<const uint8_t*>(&in);
|
||||
return Write(begin, begin + sizeof(T));
|
||||
const auto begin = ∈
|
||||
return Write(begin, begin + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize aArg using Arg's QueueParamTraits.
|
||||
*/
|
||||
template <typename Arg>
|
||||
QueueStatus WriteParam(const Arg& aArg) {
|
||||
bool WriteParam(const Arg& aArg) {
|
||||
return mozilla::webgl::QueueParamTraits<
|
||||
typename RemoveCVR<Arg>::Type>::Write(*this, aArg);
|
||||
}
|
||||
|
||||
QueueStatus GetStatus() { return mStatus; }
|
||||
bool Ok() const { return mOk; }
|
||||
|
||||
private:
|
||||
Producer* mProducer;
|
||||
size_t mRead;
|
||||
size_t* mWrite;
|
||||
QueueStatus mStatus;
|
||||
Producer* const mProducer;
|
||||
bool mOk = true;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -219,48 +133,42 @@ class ConsumerView {
|
|||
public:
|
||||
using Consumer = _Consumer;
|
||||
|
||||
ConsumerView(Consumer* aConsumer, size_t* aRead, size_t aWrite)
|
||||
: mConsumer(aConsumer),
|
||||
mRead(aRead),
|
||||
mWrite(aWrite),
|
||||
mStatus(QueueStatus::kSuccess) {}
|
||||
explicit ConsumerView(Consumer* aConsumer)
|
||||
: mConsumer(aConsumer) {}
|
||||
|
||||
/**
|
||||
* Read bytes from the consumer if there is enough data. aBuffer may
|
||||
* be null (in which case the data is skipped)
|
||||
*/
|
||||
template <typename T>
|
||||
inline QueueStatus Read(T* const destBegin, T* const destEnd) {
|
||||
inline bool Read(T* const destBegin, T* const destEnd) {
|
||||
MOZ_ASSERT(destBegin);
|
||||
MOZ_RELEASE_ASSERT(destBegin <= destEnd);
|
||||
if (!mStatus) return mStatus;
|
||||
|
||||
const auto dest = AsRange(destBegin, destEnd);
|
||||
const auto view = ReadRange<T>(dest.length());
|
||||
if (!view) return mStatus;
|
||||
if (MOZ_LIKELY(view)) {
|
||||
const auto byteSize = ByteSize(dest);
|
||||
if (byteSize) {
|
||||
if (MOZ_LIKELY(byteSize)) {
|
||||
memcpy(dest.begin().get(), view->begin().get(), byteSize);
|
||||
}
|
||||
return mStatus;
|
||||
}
|
||||
return mOk;
|
||||
}
|
||||
|
||||
/// Return a view wrapping the shmem.
|
||||
template <typename T>
|
||||
inline Maybe<Range<const T>> ReadRange(const size_t elemCount) {
|
||||
if (!mStatus) return {};
|
||||
if (MOZ_UNLIKELY(!mOk)) return {};
|
||||
const auto view = mConsumer->template ReadRange<T>(elemCount);
|
||||
if (!view) {
|
||||
mStatus = QueueStatus::kTooSmall;
|
||||
}
|
||||
mOk &= bool(view);
|
||||
return view;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline QueueStatus ReadPod(T* out) {
|
||||
inline bool ReadPod(T* out) {
|
||||
static_assert(std::is_trivially_copyable_v<T>);
|
||||
const auto begin = reinterpret_cast<uint8_t*>(out);
|
||||
return Read(begin, begin + sizeof(T));
|
||||
return Read(out, out + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -268,19 +176,17 @@ class ConsumerView {
|
|||
* If the return value is not Success then aArg is not changed.
|
||||
*/
|
||||
template <typename Arg>
|
||||
QueueStatus ReadParam(Arg* aArg) {
|
||||
bool ReadParam(Arg* aArg) {
|
||||
MOZ_ASSERT(aArg);
|
||||
return mozilla::webgl::QueueParamTraits<std::remove_cv_t<Arg>>::Read(*this,
|
||||
aArg);
|
||||
}
|
||||
|
||||
QueueStatus GetStatus() { return mStatus; }
|
||||
bool Ok() const { return mOk; }
|
||||
|
||||
private:
|
||||
Consumer* mConsumer;
|
||||
size_t* mRead;
|
||||
size_t mWrite;
|
||||
QueueStatus mStatus;
|
||||
Consumer* const mConsumer;
|
||||
bool mOk = true;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
|
@ -291,7 +197,7 @@ class ConsumerView {
|
|||
template <typename Arg>
|
||||
struct QueueParamTraits {
|
||||
template <typename U>
|
||||
static QueueStatus Write(ProducerView<U>& aProducerView, const Arg& aArg) {
|
||||
static bool Write(ProducerView<U>& aProducerView, const Arg& aArg) {
|
||||
static_assert(mozilla::webgl::template IsTriviallySerializable<Arg>::value,
|
||||
"No QueueParamTraits specialization was found for this type "
|
||||
"and it does not satisfy IsTriviallySerializable.");
|
||||
|
@ -301,7 +207,7 @@ struct QueueParamTraits {
|
|||
}
|
||||
|
||||
template <typename U>
|
||||
static QueueStatus Read(ConsumerView<U>& aConsumerView, Arg* aArg) {
|
||||
static bool Read(ConsumerView<U>& aConsumerView, Arg* aArg) {
|
||||
static_assert(mozilla::webgl::template IsTriviallySerializable<Arg>::value,
|
||||
"No QueueParamTraits specialization was found for this type "
|
||||
"and it does not satisfy IsTriviallySerializable.");
|
||||
|
@ -317,20 +223,20 @@ struct QueueParamTraits<bool> {
|
|||
using ParamType = bool;
|
||||
|
||||
template <typename U>
|
||||
static QueueStatus Write(ProducerView<U>& aProducerView,
|
||||
static auto Write(ProducerView<U>& aProducerView,
|
||||
const ParamType& aArg) {
|
||||
uint8_t temp = aArg ? 1 : 0;
|
||||
return aProducerView.WriteParam(temp);
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
static QueueStatus Read(ConsumerView<U>& aConsumerView, ParamType* aArg) {
|
||||
static auto Read(ConsumerView<U>& aConsumerView, ParamType* aArg) {
|
||||
uint8_t temp;
|
||||
if (IsSuccess(aConsumerView.ReadParam(&temp))) {
|
||||
if (aConsumerView.ReadParam(&temp)) {
|
||||
MOZ_ASSERT(temp == 1 || temp == 0);
|
||||
*aArg = temp ? true : false;
|
||||
}
|
||||
return aConsumerView.GetStatus();
|
||||
return aConsumerView.Ok();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -345,7 +251,7 @@ struct EnumSerializer {
|
|||
using DataType = typename std::underlying_type<E>::type;
|
||||
|
||||
template <typename U>
|
||||
static QueueStatus Write(ProducerView<U>& aProducerView,
|
||||
static auto Write(ProducerView<U>& aProducerView,
|
||||
const ParamType& aValue) {
|
||||
MOZ_RELEASE_ASSERT(
|
||||
EnumValidator::IsLegalValue(static_cast<DataType>(aValue)));
|
||||
|
@ -353,21 +259,21 @@ struct EnumSerializer {
|
|||
}
|
||||
|
||||
template <typename U>
|
||||
static QueueStatus Read(ConsumerView<U>& aConsumerView, ParamType* aResult) {
|
||||
static bool Read(ConsumerView<U>& aConsumerView, ParamType* aResult) {
|
||||
DataType value;
|
||||
if (!aConsumerView.ReadParam(&value)) {
|
||||
CrashReporter::AnnotateCrashReport(
|
||||
CrashReporter::Annotation::IPCReadErrorReason, "Bad iter"_ns);
|
||||
return aConsumerView.GetStatus();
|
||||
return false;
|
||||
}
|
||||
if (!EnumValidator::IsLegalValue(static_cast<DataType>(value))) {
|
||||
CrashReporter::AnnotateCrashReport(
|
||||
CrashReporter::Annotation::IPCReadErrorReason, "Illegal value"_ns);
|
||||
return QueueStatus::kFatalError;
|
||||
return false;
|
||||
}
|
||||
|
||||
*aResult = ParamType(value);
|
||||
return QueueStatus::kSuccess;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -386,19 +292,12 @@ struct ContiguousEnumSerializerInclusive
|
|||
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
template <>
|
||||
struct QueueParamTraits<QueueStatus>
|
||||
: public ContiguousEnumSerializerInclusive<
|
||||
QueueStatus, QueueStatus::kSuccess, QueueStatus::kOOMError> {};
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
template <>
|
||||
struct QueueParamTraits<webgl::TexUnpackBlobDesc> {
|
||||
using ParamType = webgl::TexUnpackBlobDesc;
|
||||
|
||||
template <typename U>
|
||||
static QueueStatus Write(ProducerView<U>& view, const ParamType& in) {
|
||||
static bool Write(ProducerView<U>& view, const ParamType& in) {
|
||||
MOZ_RELEASE_ASSERT(!in.image);
|
||||
const bool isDataSurf = bool(in.dataSurf);
|
||||
if (!view.WriteParam(in.imageTarget) || !view.WriteParam(in.size) ||
|
||||
|
@ -407,33 +306,33 @@ struct QueueParamTraits<webgl::TexUnpackBlobDesc> {
|
|||
!view.WriteParam(in.imageSize) || !view.WriteParam(in.sd) ||
|
||||
!view.WriteParam(in.applyUnpackTransforms) ||
|
||||
!view.WriteParam(isDataSurf)) {
|
||||
return view.GetStatus();
|
||||
return false;
|
||||
}
|
||||
if (isDataSurf) {
|
||||
const auto& surf = in.dataSurf;
|
||||
gfx::DataSourceSurface::ScopedMap map(surf, gfx::DataSourceSurface::READ);
|
||||
if (!map.IsMapped()) {
|
||||
return QueueStatus::kOOMError;
|
||||
return false;
|
||||
}
|
||||
const auto& surfSize = surf->GetSize();
|
||||
const auto stride = *MaybeAs<size_t>(map.GetStride());
|
||||
if (!view.WriteParam(surfSize) || !view.WriteParam(surf->GetFormat()) ||
|
||||
!view.WriteParam(stride)) {
|
||||
return view.GetStatus();
|
||||
return false;
|
||||
}
|
||||
|
||||
const size_t dataSize = stride * surfSize.height;
|
||||
const auto& begin = map.GetData();
|
||||
const auto range = Range<const uint8_t>{begin, dataSize};
|
||||
if (!view.WriteFromRange(range)) {
|
||||
return view.GetStatus();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return QueueStatus::kSuccess;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
static QueueStatus Read(ConsumerView<U>& view, ParamType* const out) {
|
||||
static bool Read(ConsumerView<U>& view, ParamType* const out) {
|
||||
bool isDataSurf;
|
||||
if (!view.ReadParam(&out->imageTarget) || !view.ReadParam(&out->size) ||
|
||||
!view.ReadParam(&out->srcAlphaType) ||
|
||||
|
@ -442,7 +341,7 @@ struct QueueParamTraits<webgl::TexUnpackBlobDesc> {
|
|||
!view.ReadParam(&out->sd) ||
|
||||
!view.ReadParam(&out->applyUnpackTransforms) ||
|
||||
!view.ReadParam(&isDataSurf)) {
|
||||
return view.GetStatus();
|
||||
return false;
|
||||
}
|
||||
if (isDataSurf) {
|
||||
gfx::IntSize surfSize;
|
||||
|
@ -450,11 +349,11 @@ struct QueueParamTraits<webgl::TexUnpackBlobDesc> {
|
|||
size_t stride;
|
||||
if (!view.ReadParam(&surfSize) || !view.ReadParam(&format) ||
|
||||
!view.ReadParam(&stride)) {
|
||||
return view.GetStatus();
|
||||
return false;
|
||||
}
|
||||
const size_t dataSize = stride * surfSize.height;
|
||||
const auto range = view.template ReadRange<uint8_t>(dataSize);
|
||||
if (!range) return view.GetStatus();
|
||||
if (!range) return false;
|
||||
|
||||
// DataSourceSurface demands pointer-to-mutable.
|
||||
const auto bytes = const_cast<uint8_t*>(range->begin().get());
|
||||
|
@ -462,7 +361,7 @@ struct QueueParamTraits<webgl::TexUnpackBlobDesc> {
|
|||
bytes, stride, surfSize, format);
|
||||
MOZ_ASSERT(out->dataSurf);
|
||||
}
|
||||
return QueueStatus::kSuccess;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -473,51 +372,51 @@ struct QueueParamTraits<nsACString> {
|
|||
using ParamType = nsACString;
|
||||
|
||||
template <typename U>
|
||||
static QueueStatus Write(ProducerView<U>& aProducerView,
|
||||
static bool Write(ProducerView<U>& aProducerView,
|
||||
const ParamType& aArg) {
|
||||
if ((!aProducerView.WriteParam(aArg.IsVoid())) || aArg.IsVoid()) {
|
||||
return aProducerView.GetStatus();
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t len = aArg.Length();
|
||||
if ((!aProducerView.WriteParam(len)) || (len == 0)) {
|
||||
return aProducerView.GetStatus();
|
||||
return false;
|
||||
}
|
||||
|
||||
return aProducerView.Write(aArg.BeginReading(), len);
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
static QueueStatus Read(ConsumerView<U>& aConsumerView, ParamType* aArg) {
|
||||
static bool Read(ConsumerView<U>& aConsumerView, ParamType* aArg) {
|
||||
bool isVoid = false;
|
||||
if (!IsSuccess(aConsumerView.ReadParam(&isVoid))) {
|
||||
return aConsumerView.GetStatus();
|
||||
if (!aConsumerView.ReadParam(&isVoid)) {
|
||||
return false;
|
||||
}
|
||||
aArg->SetIsVoid(isVoid);
|
||||
if (isVoid) {
|
||||
return QueueStatus::kSuccess;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t len = 0;
|
||||
if (!IsSuccess(aConsumerView.ReadParam(&len))) {
|
||||
return aConsumerView.GetStatus();
|
||||
if (!aConsumerView.ReadParam(&len)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (len == 0) {
|
||||
*aArg = "";
|
||||
return QueueStatus::kSuccess;
|
||||
return true;
|
||||
}
|
||||
|
||||
char* buf = new char[len + 1];
|
||||
if (!buf) {
|
||||
return QueueStatus::kOOMError;
|
||||
return false;
|
||||
}
|
||||
if (!IsSuccess(aConsumerView.Read(buf, len))) {
|
||||
return aConsumerView.GetStatus();
|
||||
if (!aConsumerView.Read(buf, len)) {
|
||||
return false;
|
||||
}
|
||||
buf[len] = '\0';
|
||||
aArg->Adopt(buf, len);
|
||||
return QueueStatus::kSuccess;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -526,40 +425,40 @@ struct QueueParamTraits<nsAString> {
|
|||
using ParamType = nsAString;
|
||||
|
||||
template <typename U>
|
||||
static QueueStatus Write(ProducerView<U>& aProducerView,
|
||||
static bool Write(ProducerView<U>& aProducerView,
|
||||
const ParamType& aArg) {
|
||||
if ((!aProducerView.WriteParam(aArg.IsVoid())) || (aArg.IsVoid())) {
|
||||
return aProducerView.GetStatus();
|
||||
return false;
|
||||
}
|
||||
// DLP: No idea if this includes null terminator
|
||||
uint32_t len = aArg.Length();
|
||||
if ((!aProducerView.WriteParam(len)) || (len == 0)) {
|
||||
return aProducerView.GetStatus();
|
||||
return false;
|
||||
}
|
||||
constexpr const uint32_t sizeofchar = sizeof(typename ParamType::char_type);
|
||||
return aProducerView.Write(aArg.BeginReading(), len * sizeofchar);
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
static QueueStatus Read(ConsumerView<U>& aConsumerView, ParamType* aArg) {
|
||||
static bool Read(ConsumerView<U>& aConsumerView, ParamType* aArg) {
|
||||
bool isVoid = false;
|
||||
if (!aConsumerView.ReadParam(&isVoid)) {
|
||||
return aConsumerView.GetStatus();
|
||||
return false;
|
||||
}
|
||||
aArg->SetIsVoid(isVoid);
|
||||
if (isVoid) {
|
||||
return QueueStatus::kSuccess;
|
||||
return true;
|
||||
}
|
||||
|
||||
// DLP: No idea if this includes null terminator
|
||||
uint32_t len = 0;
|
||||
if (!aConsumerView.ReadParam(&len)) {
|
||||
return aConsumerView.GetStatus();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (len == 0) {
|
||||
*aArg = nsString();
|
||||
return QueueStatus::kSuccess;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t sizeofchar = sizeof(typename ParamType::char_type);
|
||||
|
@ -567,16 +466,16 @@ struct QueueParamTraits<nsAString> {
|
|||
buf = static_cast<typename ParamType::char_type*>(
|
||||
malloc((len + 1) * sizeofchar));
|
||||
if (!buf) {
|
||||
return QueueStatus::kOOMError;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!aConsumerView.Read(buf, len * sizeofchar)) {
|
||||
return aConsumerView.GetStatus();
|
||||
return false;
|
||||
}
|
||||
|
||||
buf[len] = L'\0';
|
||||
aArg->Adopt(buf, len);
|
||||
return QueueStatus::kSuccess;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -604,31 +503,31 @@ struct NSArrayQueueParamTraits<nsTArray<_ElementType>, false> {
|
|||
using ParamType = nsTArray<ElementType>;
|
||||
|
||||
template <typename U>
|
||||
static QueueStatus Write(ProducerView<U>& aProducerView,
|
||||
static bool Write(ProducerView<U>& aProducerView,
|
||||
const ParamType& aArg) {
|
||||
aProducerView.WriteParam(aArg.Length());
|
||||
for (auto& elt : aArg) {
|
||||
aProducerView.WriteParam(elt);
|
||||
}
|
||||
return aProducerView.GetStatus();
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
static QueueStatus Read(ConsumerView<U>& aConsumerView, ParamType* aArg) {
|
||||
static bool Read(ConsumerView<U>& aConsumerView, ParamType* aArg) {
|
||||
size_t arrayLen;
|
||||
if (!aConsumerView.ReadParam(&arrayLen)) {
|
||||
return aConsumerView.GetStatus();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!aArg->AppendElements(arrayLen, fallible)) {
|
||||
return QueueStatus::kOOMError;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto i : IntegerRange(arrayLen)) {
|
||||
ElementType& elt = aArg->ElementAt(i);
|
||||
aConsumerView.ReadParam(elt);
|
||||
}
|
||||
return aConsumerView.GetStatus();
|
||||
return aConsumerView.Ok();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -640,7 +539,7 @@ struct NSArrayQueueParamTraits<nsTArray<_ElementType>, true> {
|
|||
|
||||
// TODO: Are there alignment issues?
|
||||
template <typename U>
|
||||
static QueueStatus Write(ProducerView<U>& aProducerView,
|
||||
static bool Write(ProducerView<U>& aProducerView,
|
||||
const ParamType& aArg) {
|
||||
size_t arrayLen = aArg.Length();
|
||||
aProducerView.WriteParam(arrayLen);
|
||||
|
@ -648,14 +547,14 @@ struct NSArrayQueueParamTraits<nsTArray<_ElementType>, true> {
|
|||
}
|
||||
|
||||
template <typename U>
|
||||
static QueueStatus Read(ConsumerView<U>& aConsumerView, ParamType* aArg) {
|
||||
static bool Read(ConsumerView<U>& aConsumerView, ParamType* aArg) {
|
||||
size_t arrayLen;
|
||||
if (!aConsumerView.ReadParam(&arrayLen)) {
|
||||
return aConsumerView.GetStatus();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!aArg->AppendElements(arrayLen, fallible)) {
|
||||
return QueueStatus::kOOMError;
|
||||
return false;
|
||||
}
|
||||
|
||||
return aConsumerView.Read(aArg->Elements(), arrayLen * sizeof(ElementType));
|
||||
|
@ -682,20 +581,20 @@ struct ArrayQueueParamTraits<Array<_ElementType, Length>, false> {
|
|||
using ParamType = Array<ElementType, Length>;
|
||||
|
||||
template <typename U>
|
||||
static QueueStatus Write(ProducerView<U>& aProducerView,
|
||||
static auto Write(ProducerView<U>& aProducerView,
|
||||
const ParamType& aArg) {
|
||||
for (const auto& elt : aArg) {
|
||||
aProducerView.WriteParam(elt);
|
||||
}
|
||||
return aProducerView.GetStatus();
|
||||
return aProducerView.Ok();
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
static QueueStatus Read(ConsumerView<U>& aConsumerView, ParamType* aArg) {
|
||||
static auto Read(ConsumerView<U>& aConsumerView, ParamType* aArg) {
|
||||
for (auto& elt : *aArg) {
|
||||
aConsumerView.ReadParam(elt);
|
||||
}
|
||||
return aConsumerView.GetStatus();
|
||||
return aConsumerView.Ok();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -706,13 +605,13 @@ struct ArrayQueueParamTraits<Array<_ElementType, Length>, true> {
|
|||
using ParamType = Array<ElementType, Length>;
|
||||
|
||||
template <typename U>
|
||||
static QueueStatus Write(ProducerView<U>& aProducerView,
|
||||
static auto Write(ProducerView<U>& aProducerView,
|
||||
const ParamType& aArg) {
|
||||
return aProducerView.Write(aArg.begin(), sizeof(ElementType[Length]));
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
static QueueStatus Read(ConsumerView<U>& aConsumerView, ParamType* aArg) {
|
||||
static auto Read(ConsumerView<U>& aConsumerView, ParamType* aArg) {
|
||||
return aConsumerView.Read(aArg->begin(), sizeof(ElementType[Length]));
|
||||
}
|
||||
};
|
||||
|
@ -730,23 +629,25 @@ struct QueueParamTraits<Maybe<ElementType>> {
|
|||
using ParamType = Maybe<ElementType>;
|
||||
|
||||
template <typename U>
|
||||
static QueueStatus Write(ProducerView<U>& aProducerView,
|
||||
static bool Write(ProducerView<U>& aProducerView,
|
||||
const ParamType& aArg) {
|
||||
aProducerView.WriteParam(static_cast<bool>(aArg));
|
||||
return aArg ? aProducerView.WriteParam(aArg.ref())
|
||||
: aProducerView.GetStatus();
|
||||
if (aArg) {
|
||||
aProducerView.WriteParam(aArg.ref());
|
||||
}
|
||||
return aProducerView.Ok();
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
static QueueStatus Read(ConsumerView<U>& aConsumerView, ParamType* aArg) {
|
||||
static bool Read(ConsumerView<U>& aConsumerView, ParamType* aArg) {
|
||||
bool isSome;
|
||||
if (!aConsumerView.ReadParam(&isSome)) {
|
||||
return aConsumerView.GetStatus();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isSome) {
|
||||
aArg->reset();
|
||||
return QueueStatus::kSuccess;
|
||||
return true;
|
||||
}
|
||||
|
||||
aArg->emplace();
|
||||
|
@ -756,52 +657,19 @@ struct QueueParamTraits<Maybe<ElementType>> {
|
|||
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
// Maybe<Variant> needs special behavior since Variant is not default
|
||||
// constructable. The Variant's first type must be default constructible.
|
||||
template <typename T, typename... Ts>
|
||||
struct QueueParamTraits<Maybe<Variant<T, Ts...>>> {
|
||||
using ParamType = Maybe<Variant<T, Ts...>>;
|
||||
|
||||
template <typename U>
|
||||
static QueueStatus Write(ProducerView<U>& aProducerView,
|
||||
const ParamType& aArg) {
|
||||
aProducerView.WriteParam(aArg.mIsSome);
|
||||
return (aArg.mIsSome) ? aProducerView.WriteParam(aArg.ref())
|
||||
: aProducerView.GetStatus();
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
static QueueStatus Read(ConsumerView<U>& aConsumerView, ParamType* aArg) {
|
||||
bool isSome;
|
||||
if (!aConsumerView.ReadParam(&isSome)) {
|
||||
return aConsumerView.GetStatus();
|
||||
}
|
||||
|
||||
if (!isSome) {
|
||||
aArg->reset();
|
||||
return QueueStatus::kSuccess;
|
||||
}
|
||||
|
||||
aArg->emplace(VariantType<T>());
|
||||
return aConsumerView.ReadParam(aArg->ptr());
|
||||
}
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
template <typename TypeA, typename TypeB>
|
||||
struct QueueParamTraits<std::pair<TypeA, TypeB>> {
|
||||
using ParamType = std::pair<TypeA, TypeB>;
|
||||
|
||||
template <typename U>
|
||||
static QueueStatus Write(ProducerView<U>& aProducerView,
|
||||
static bool Write(ProducerView<U>& aProducerView,
|
||||
const ParamType& aArg) {
|
||||
aProducerView.WriteParam(aArg.first());
|
||||
return aProducerView.WriteParam(aArg.second());
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
static QueueStatus Read(ConsumerView<U>& aConsumerView, ParamType* aArg) {
|
||||
static bool Read(ConsumerView<U>& aConsumerView, ParamType* aArg) {
|
||||
aConsumerView.ReadParam(aArg->first());
|
||||
return aConsumerView.ReadParam(aArg->second());
|
||||
}
|
||||
|
@ -809,49 +677,15 @@ struct QueueParamTraits<std::pair<TypeA, TypeB>> {
|
|||
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
template <typename T>
|
||||
struct QueueParamTraits<UniquePtr<T>> {
|
||||
using ParamType = UniquePtr<T>;
|
||||
|
||||
template <typename U>
|
||||
static QueueStatus Write(ProducerView<U>& aProducerView,
|
||||
const ParamType& aArg) {
|
||||
// TODO: Clean up move with PCQ
|
||||
aProducerView.WriteParam(!static_cast<bool>(aArg));
|
||||
if (aArg && aProducerView.WriteParam(*aArg.get())) {
|
||||
const_cast<ParamType&>(aArg).reset();
|
||||
}
|
||||
return aProducerView.GetStatus();
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
static QueueStatus Read(ConsumerView<U>& aConsumerView, ParamType* aArg) {
|
||||
bool isNull;
|
||||
if (!aConsumerView.ReadParam(&isNull)) {
|
||||
return aConsumerView.GetStatus();
|
||||
}
|
||||
if (isNull) {
|
||||
aArg->reset(nullptr);
|
||||
return QueueStatus::kSuccess;
|
||||
}
|
||||
|
||||
T* obj = new T();
|
||||
aArg->reset(obj);
|
||||
return aConsumerView.ReadParam(obj);
|
||||
}
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
template <>
|
||||
struct QueueParamTraits<mozilla::ipc::Shmem> {
|
||||
using ParamType = mozilla::ipc::Shmem;
|
||||
|
||||
template <typename U>
|
||||
static QueueStatus Write(ProducerView<U>& aProducerView, ParamType&& aParam) {
|
||||
static bool Write(ProducerView<U>& aProducerView, ParamType&& aParam) {
|
||||
if (!aProducerView.WriteParam(
|
||||
aParam.Id(mozilla::ipc::Shmem::PrivateIPDLCaller()))) {
|
||||
return aProducerView.GetStatus();
|
||||
return false;
|
||||
}
|
||||
|
||||
aParam.RevokeRights(mozilla::ipc::Shmem::PrivateIPDLCaller());
|
||||
|
@ -859,21 +693,21 @@ struct QueueParamTraits<mozilla::ipc::Shmem> {
|
|||
}
|
||||
|
||||
template <typename U>
|
||||
static QueueStatus Read(ConsumerView<U>& aConsumerView, ParamType* aResult) {
|
||||
static bool Read(ConsumerView<U>& aConsumerView, ParamType* aResult) {
|
||||
ParamType::id_t id;
|
||||
if (!aConsumerView.ReadParam(&id)) {
|
||||
return aConsumerView.GetStatus();
|
||||
return false;
|
||||
}
|
||||
|
||||
mozilla::ipc::Shmem::SharedMemory* rawmem =
|
||||
aConsumerView.LookupSharedMemory(id);
|
||||
if (!rawmem) {
|
||||
return QueueStatus::kFatalError;
|
||||
return false;
|
||||
}
|
||||
|
||||
*aResult = mozilla::ipc::Shmem(mozilla::ipc::Shmem::PrivateIPDLCaller(),
|
||||
rawmem, id);
|
||||
return QueueStatus::kSuccess;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -6,20 +6,9 @@
|
|||
#ifndef WEBGLCHILD_H_
|
||||
#define WEBGLCHILD_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "mozilla/dom/PWebGLChild.h"
|
||||
#include "mozilla/dom/IpdlQueue.h"
|
||||
|
||||
// This is a bit weird. Nothing directly in WebGLChild.h necessitates including
|
||||
// WebGLParent.h, but if we don't do this, we get compiler errors in the
|
||||
// generated code inside PWebGLChild.cpp. The error is due to a complex
|
||||
// dependency chain involving IpdlQueue, which I won't go into here. Including
|
||||
// WebGLParent.h inside WebGLChild.h is the simplest way we could think of to
|
||||
// avoid this issue. Including it in any of the code more directly involved in
|
||||
// the breaking dependency chain unfortunately introduces a cyclical dependency
|
||||
// between WebGLParent.h and PWebGLParent.h.
|
||||
#include "mozilla/dom/WebGLParent.h"
|
||||
#include <string>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -41,7 +30,6 @@ class WebGLChild final : public PWebGLChild, public SupportsWeakPtr {
|
|||
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebGLChild, override);
|
||||
using OtherSideActor = WebGLParent;
|
||||
|
||||
explicit WebGLChild(ClientWebGLContext&);
|
||||
|
||||
|
|
|
@ -15,8 +15,6 @@
|
|||
|
||||
namespace mozilla {
|
||||
|
||||
using webgl::QueueStatus;
|
||||
|
||||
namespace webgl {
|
||||
|
||||
class RangeConsumerView final : public webgl::ConsumerView<RangeConsumerView> {
|
||||
|
@ -27,7 +25,7 @@ class RangeConsumerView final : public webgl::ConsumerView<RangeConsumerView> {
|
|||
auto Remaining() const { return *MaybeAs<size_t>(mSrcEnd - mSrcItr); }
|
||||
|
||||
explicit RangeConsumerView(const Range<const uint8_t> range)
|
||||
: ConsumerView(this, nullptr, 0),
|
||||
: ConsumerView(this),
|
||||
mSrcItr(range.begin()),
|
||||
mSrcEnd(range.end()) {
|
||||
(void)Remaining(); // assert size non-negative
|
||||
|
@ -35,7 +33,7 @@ class RangeConsumerView final : public webgl::ConsumerView<RangeConsumerView> {
|
|||
|
||||
void AlignTo(const size_t alignment) {
|
||||
const auto offset = AlignmentOffset(alignment, mSrcItr.get());
|
||||
if (offset > Remaining()) {
|
||||
if (MOZ_UNLIKELY(offset > Remaining())) {
|
||||
mSrcItr = mSrcEnd;
|
||||
return;
|
||||
}
|
||||
|
@ -52,7 +50,7 @@ class RangeConsumerView final : public webgl::ConsumerView<RangeConsumerView> {
|
|||
const auto& byteSize = byteSizeChecked.value();
|
||||
|
||||
const auto remaining = Remaining();
|
||||
if (byteSize > remaining) return {};
|
||||
if (MOZ_UNLIKELY(byteSize > remaining)) return {};
|
||||
|
||||
const auto begin = reinterpret_cast<const T*>(mSrcItr.get());
|
||||
mSrcItr += byteSize;
|
||||
|
@ -69,10 +67,10 @@ class SizeOnlyProducerView final
|
|||
size_t mRequiredSize = 0;
|
||||
|
||||
public:
|
||||
SizeOnlyProducerView() : ProducerView(this, 0, nullptr) {}
|
||||
SizeOnlyProducerView() : ProducerView(this) {}
|
||||
|
||||
template <typename T>
|
||||
void WriteFromRange(const Range<const T>& src) {
|
||||
bool WriteFromRange(const Range<const T>& src) {
|
||||
constexpr auto alignment = alignof(T);
|
||||
const size_t byteSize = ByteSize(src);
|
||||
// printf_stderr("SizeOnlyProducerView: @%zu +%zu\n", alignment, byteSize);
|
||||
|
@ -81,6 +79,7 @@ class SizeOnlyProducerView final
|
|||
mRequiredSize += offset;
|
||||
|
||||
mRequiredSize += byteSize;
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto& RequiredSize() const { return mRequiredSize; }
|
||||
|
@ -97,7 +96,7 @@ class RangeProducerView final : public webgl::ProducerView<RangeProducerView> {
|
|||
auto Remaining() const { return *MaybeAs<size_t>(mDestEnd - mDestItr); }
|
||||
|
||||
explicit RangeProducerView(const Range<uint8_t> range)
|
||||
: ProducerView(this, 0, nullptr),
|
||||
: ProducerView(this),
|
||||
mDestBegin(range.begin()),
|
||||
mDestEnd(range.end()),
|
||||
mDestItr(mDestBegin) {
|
||||
|
@ -105,7 +104,7 @@ class RangeProducerView final : public webgl::ProducerView<RangeProducerView> {
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
void WriteFromRange(const Range<const T>& src) {
|
||||
bool WriteFromRange(const Range<const T>& src) {
|
||||
constexpr auto alignment = alignof(T);
|
||||
const size_t byteSize = ByteSize(src);
|
||||
// printf_stderr("RangeProducerView: @%zu +%zu\n", alignment, byteSize);
|
||||
|
@ -114,10 +113,11 @@ class RangeProducerView final : public webgl::ProducerView<RangeProducerView> {
|
|||
mDestItr += offset;
|
||||
|
||||
MOZ_ASSERT(byteSize <= Remaining());
|
||||
if (byteSize) {
|
||||
if (MOZ_LIKELY(byteSize)) {
|
||||
memcpy(mDestItr.get(), src.begin().get(), byteSize);
|
||||
}
|
||||
mDestItr += byteSize;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -129,7 +129,7 @@ inline void Serialize(ProducerViewT&) {}
|
|||
template <typename ProducerViewT, typename Arg, typename... Args>
|
||||
inline void Serialize(ProducerViewT& view, const Arg& arg,
|
||||
const Args&... args) {
|
||||
MOZ_ALWAYS_TRUE(view.WriteParam(arg) == QueueStatus::kSuccess);
|
||||
MOZ_ALWAYS_TRUE(view.WriteParam(arg));
|
||||
Serialize(view, args...);
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "mozilla/gfx/gfxVars.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/ProcessPriorityManager.h"
|
||||
#include "mozilla/ResultVariant.h"
|
||||
#include "mozilla/ScopeExit.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/StaticPrefs_webgl.h"
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "WebGLVertexArray.h"
|
||||
|
||||
#include "mozilla/Casting.h"
|
||||
#include "mozilla/ResultVariant.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
|
|
@ -54,8 +54,7 @@ IPCResult WebGLParent::RecvDispatchCommands(Shmem&& rawShmem,
|
|||
while (true) {
|
||||
view.AlignTo(kUniversalAlignment);
|
||||
size_t id = 0;
|
||||
const auto status = view.ReadParam(&id);
|
||||
if (status != QueueStatus::kSuccess) break;
|
||||
if (!view.ReadParam(&id)) break;
|
||||
|
||||
const auto ok = WebGLMethodDispatcher<0>::DispatchCommand(*mHost, id, view);
|
||||
if (!ok) {
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#include "mozilla/GfxMessageUtils.h"
|
||||
#include "mozilla/dom/PWebGLParent.h"
|
||||
#include "mozilla/WeakPtr.h"
|
||||
#include "mozilla/dom/IpdlQueue.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -28,7 +27,6 @@ class WebGLParent : public PWebGLParent, public SupportsWeakPtr {
|
|||
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebGLParent, override);
|
||||
using OtherSideActor = WebGLChild;
|
||||
|
||||
mozilla::ipc::IPCResult RecvInitialize(const webgl::InitContextDesc&,
|
||||
webgl::InitContextResult* out);
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
|
@ -75,7 +76,7 @@ struct QueueParamTraits<RawBuffer<T>> {
|
|||
using ParamType = RawBuffer<T>;
|
||||
|
||||
template <typename U>
|
||||
static QueueStatus Write(ProducerView<U>& view, const ParamType& in) {
|
||||
static bool Write(ProducerView<U>& view, const ParamType& in) {
|
||||
const auto& elemCount = in.size();
|
||||
auto status = view.WriteParam(elemCount);
|
||||
if (!status) return status;
|
||||
|
@ -92,13 +93,13 @@ struct QueueParamTraits<RawBuffer<T>> {
|
|||
}
|
||||
|
||||
template <typename U>
|
||||
static QueueStatus Read(ConsumerView<U>& view, ParamType* const out) {
|
||||
static bool Read(ConsumerView<U>& view, ParamType* const out) {
|
||||
size_t elemCount = 0;
|
||||
auto status = view.ReadParam(&elemCount);
|
||||
if (!status) return status;
|
||||
if (!elemCount) {
|
||||
*out = {};
|
||||
return QueueStatus::kSuccess;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t hasData = 0;
|
||||
|
@ -107,13 +108,13 @@ struct QueueParamTraits<RawBuffer<T>> {
|
|||
if (!hasData) {
|
||||
auto temp = RawBuffer<T>{elemCount};
|
||||
*out = std::move(temp);
|
||||
return QueueStatus::kSuccess;
|
||||
return true;
|
||||
}
|
||||
|
||||
auto data = view.template ReadRange<T>(elemCount);
|
||||
if (!data) return QueueStatus::kTooSmall;
|
||||
if (!data) return false;
|
||||
*out = std::move(RawBuffer<T>{*data});
|
||||
return QueueStatus::kSuccess;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -128,7 +129,7 @@ struct QueueParamTraits<Result<V, E>> {
|
|||
using T = Result<V, E>;
|
||||
|
||||
template <typename U>
|
||||
static QueueStatus Write(ProducerView<U>& aProducerView, const T& aArg) {
|
||||
static bool Write(ProducerView<U>& aProducerView, const T& aArg) {
|
||||
const auto ok = aArg.isOk();
|
||||
auto status = aProducerView.WriteParam(ok);
|
||||
if (!status) return status;
|
||||
|
@ -141,7 +142,7 @@ struct QueueParamTraits<Result<V, E>> {
|
|||
}
|
||||
|
||||
template <typename U>
|
||||
static QueueStatus Read(ConsumerView<U>& aConsumerView, T* aArg) {
|
||||
static bool Read(ConsumerView<U>& aConsumerView, T* aArg) {
|
||||
bool ok;
|
||||
auto status = aConsumerView.ReadParam(&ok);
|
||||
if (!status) return status;
|
||||
|
@ -163,7 +164,7 @@ struct QueueParamTraits<std::string> {
|
|||
using T = std::string;
|
||||
|
||||
template <typename U>
|
||||
static QueueStatus Write(ProducerView<U>& aProducerView, const T& aArg) {
|
||||
static bool Write(ProducerView<U>& aProducerView, const T& aArg) {
|
||||
const auto size = aArg.size();
|
||||
auto status = aProducerView.WriteParam(size);
|
||||
if (!status) return status;
|
||||
|
@ -172,13 +173,13 @@ struct QueueParamTraits<std::string> {
|
|||
}
|
||||
|
||||
template <typename U>
|
||||
static QueueStatus Read(ConsumerView<U>& aConsumerView, T* aArg) {
|
||||
static bool Read(ConsumerView<U>& aConsumerView, T* aArg) {
|
||||
size_t size;
|
||||
auto status = aConsumerView.ReadParam(&size);
|
||||
if (!status) return status;
|
||||
|
||||
const auto view = aConsumerView.template ReadRange<char>(size);
|
||||
if (!view) return QueueStatus::kFatalError;
|
||||
if (!view) return false;
|
||||
aArg->assign(view->begin().get(), size);
|
||||
return status;
|
||||
}
|
||||
|
@ -189,7 +190,7 @@ struct QueueParamTraits<std::vector<U>> {
|
|||
using T = std::vector<U>;
|
||||
|
||||
template <typename V>
|
||||
static QueueStatus Write(ProducerView<V>& aProducerView, const T& aArg) {
|
||||
static bool Write(ProducerView<V>& aProducerView, const T& aArg) {
|
||||
auto status = aProducerView.WriteParam(aArg.size());
|
||||
if (!status) return status;
|
||||
|
||||
|
@ -201,7 +202,7 @@ struct QueueParamTraits<std::vector<U>> {
|
|||
}
|
||||
|
||||
template <typename V>
|
||||
static QueueStatus Read(ConsumerView<V>& aConsumerView, T* aArg) {
|
||||
static bool Read(ConsumerView<V>& aConsumerView, T* aArg) {
|
||||
size_t size;
|
||||
auto status = aConsumerView.ReadParam(&size);
|
||||
if (!status) return status;
|
||||
|
@ -226,7 +227,7 @@ struct QueueParamTraits<CompileResult> {
|
|||
using T = CompileResult;
|
||||
|
||||
template <typename U>
|
||||
static QueueStatus Write(ProducerView<U>& aProducerView, const T& aArg) {
|
||||
static bool Write(ProducerView<U>& aProducerView, const T& aArg) {
|
||||
aProducerView.WriteParam(aArg.pending);
|
||||
aProducerView.WriteParam(aArg.log);
|
||||
aProducerView.WriteParam(aArg.translatedSource);
|
||||
|
@ -234,7 +235,7 @@ struct QueueParamTraits<CompileResult> {
|
|||
}
|
||||
|
||||
template <typename U>
|
||||
static QueueStatus Read(ConsumerView<U>& aConsumerView, T* aArg) {
|
||||
static bool Read(ConsumerView<U>& aConsumerView, T* aArg) {
|
||||
aConsumerView.ReadParam(&aArg->pending);
|
||||
aConsumerView.ReadParam(&aArg->log);
|
||||
aConsumerView.ReadParam(&aArg->translatedSource);
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
#include "mozilla/MathAlgorithms.h"
|
||||
#include "mozilla/Range.h"
|
||||
#include "mozilla/RefCounted.h"
|
||||
#include "mozilla/ResultVariant.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/gfx/BuildConstants.h"
|
||||
#include "mozilla/gfx/Point.h"
|
||||
|
@ -355,13 +354,6 @@ struct FloatOrInt final // For TexParameter[fi] and friends.
|
|||
}
|
||||
};
|
||||
|
||||
using WebGLTexUnpackVariant =
|
||||
Variant<UniquePtr<webgl::TexUnpackBytes>,
|
||||
UniquePtr<webgl::TexUnpackSurface>,
|
||||
UniquePtr<webgl::TexUnpackImage>, WebGLTexPboOffset>;
|
||||
|
||||
using MaybeWebGLTexUnpackVariant = Maybe<WebGLTexUnpackVariant>;
|
||||
|
||||
struct WebGLContextOptions {
|
||||
bool alpha = true;
|
||||
bool depth = true;
|
||||
|
|
|
@ -59,7 +59,6 @@ EXPORTS.mozilla.dom += [
|
|||
"ImageBitmapSource.h",
|
||||
"ImageData.h",
|
||||
"ImageUtils.h",
|
||||
"IpdlQueue.h",
|
||||
"OffscreenCanvas.h",
|
||||
"QueueParamTraits.h",
|
||||
"TextMetrics.h",
|
||||
|
|
Загрузка…
Ссылка в новой задаче