Backed out 7 changesets (bug 1621762) for causing build bustages at builds/worker/workspace/obj-build/dist/include/mozilla/dom/ProducerConsumerQueue.h

CLOSED TREE

Backed out changeset 03903e8f368e (bug 1621762)
Backed out changeset 21ef72486643 (bug 1621762)
Backed out changeset 70d103786c83 (bug 1621762)
Backed out changeset a3e1332998c3 (bug 1621762)
Backed out changeset 010f653b87d2 (bug 1621762)
Backed out changeset 0496adcb4582 (bug 1621762)
Backed out changeset 8d85420fd2e6 (bug 1621762)
This commit is contained in:
Daniel Varga 2020-04-30 06:06:33 +03:00
Родитель 63b9840733
Коммит 452acadb3b
27 изменённых файлов: 1708 добавлений и 2517 удалений

Просмотреть файл

@ -461,15 +461,7 @@ void ClientWebGLContext::ClearVRFrame() const { Run<RPROC(ClearVRFrame)>(); }
RefPtr<layers::SharedSurfaceTextureClient> ClientWebGLContext::GetVRFrame(
const WebGLFramebufferJS* fb) const {
const auto notLost =
mNotLost; // Hold a strong-ref to prevent LoseContext=>UAF.
if (!notLost) return nullptr;
const auto& inProcessContext = notLost->inProcess;
if (inProcessContext) {
return inProcessContext->GetVRFrame(fb ? fb->mId : 0);
}
MOZ_ASSERT_UNREACHABLE("TODO: Remote GetVRFrame");
return nullptr;
return Run<RPROC(GetVRFrame)>(fb ? fb->mId : 0);
}
already_AddRefed<layers::Layer> ClientWebGLContext::GetCanvasLayer(
@ -732,55 +724,32 @@ bool ClientWebGLContext::CreateHostContext(const uvec2& requestedSize) {
return Err("!CompositorBridgeChild::Get()");
}
outOfProcess.mWebGLChild = new WebGLChild(*this);
outOfProcess.mWebGLChild = static_cast<dom::WebGLChild*>(
cbc->SendPWebGLConstructor(outOfProcess.mWebGLChild));
if (!outOfProcess.mWebGLChild) {
// Construct the WebGL command queue, used to send commands from the client
// process to the host for execution. It takes a response queue that is
// used to return responses to synchronous messages.
// TODO: Be smarter in choosing these.
static constexpr size_t CommandQueueSize = 256 * 1024; // 256K
static constexpr size_t ResponseQueueSize = 8 * 1024; // 8K
auto commandPcq = ProducerConsumerQueue::Create(cbc, CommandQueueSize);
auto responsePcq = ProducerConsumerQueue::Create(cbc, ResponseQueueSize);
if (!commandPcq || !responsePcq) {
return Err("Failed to create command/response PCQ");
}
outOfProcess.mCommandSource = MakeUnique<ClientWebGLCommandSource>(
std::move(commandPcq->mProducer), std::move(responsePcq->mConsumer));
auto sink = MakeUnique<HostWebGLCommandSink>(
std::move(commandPcq->mConsumer), std::move(responsePcq->mProducer));
// Use the error/warning and command queues to construct a
// ClientWebGLContext in this process and a HostWebGLContext
// in the host process.
outOfProcess.mWebGLChild = new dom::WebGLChild(*this);
if (!cbc->SendPWebGLConstructor(outOfProcess.mWebGLChild.get(), initDesc,
&notLost.info)) {
return Err("SendPWebGLConstructor failed");
}
UniquePtr<HostWebGLCommandSinkP> sinkP;
UniquePtr<HostWebGLCommandSinkI> sinkI;
switch (StaticPrefs::webgl_prototype_ipc_pcq()) {
case 0: {
using mozilla::webgl::ProducerConsumerQueue;
static constexpr size_t CommandQueueSize = 256 * 1024; // 256K
static constexpr size_t ResponseQueueSize = 8 * 1024; // 8K
auto command = ProducerConsumerQueue::Create(cbc, CommandQueueSize);
auto response = ProducerConsumerQueue::Create(cbc, ResponseQueueSize);
if (!command || !response) {
return Err("Failed to create command/response PCQ");
}
outOfProcess.mCommandSourcePcq = MakeUnique<ClientWebGLCommandSourceP>(
command->TakeProducer(), response->TakeConsumer());
sinkP = MakeUnique<HostWebGLCommandSinkP>(command->TakeConsumer(),
response->TakeProducer());
break;
}
default:
using mozilla::IpdlWebGLCommandQueue;
using mozilla::IpdlWebGLResponseQueue;
auto command =
IpdlWebGLCommandQueue::Create(outOfProcess.mWebGLChild.get());
auto response =
IpdlWebGLResponseQueue::Create(outOfProcess.mWebGLChild.get());
if (!command || !response) {
return Err("Failed to create command/response IpdlQueue");
}
outOfProcess.mCommandSourceIpdl = MakeUnique<ClientWebGLCommandSourceI>(
command->TakeProducer(), response->TakeConsumer());
sinkI = MakeUnique<HostWebGLCommandSinkI>(command->TakeConsumer(),
response->TakeProducer());
break;
}
if (!outOfProcess.mWebGLChild->SendInitialize(
initDesc, std::move(sinkP), std::move(sinkI), &notLost.info)) {
return Err("WebGL actor Initialize failed");
}
notLost.outOfProcess = Some(std::move(outOfProcess));
return Ok();
}();
@ -972,16 +941,8 @@ already_AddRefed<gfx::SourceSurface> ClientWebGLContext::GetSurfaceSnapshot(
const auto range = Range<uint8_t>(map.GetData(), stride * size.y);
auto view = RawBufferView(range);
Run<RPROC(ReadPixels)>(desc, view);
const auto notLost =
mNotLost; // Hold a strong-ref to prevent LoseContext=>UAF.
if (!notLost) return nullptr;
const auto& inProcessContext = notLost->inProcess;
if (inProcessContext) {
inProcessContext->ReadPixels(desc, view);
} else {
MOZ_ASSERT_UNREACHABLE("TODO: Remote GetSurfaceSnapshot");
}
// -
const auto swapRowRedBlue = [&](uint8_t* const row) {
@ -1623,18 +1584,8 @@ void ClientWebGLContext::GetInternalformatParameter(
JSContext* cx, GLenum target, GLenum internalformat, GLenum pname,
JS::MutableHandle<JS::Value> retval, ErrorResult& rv) {
retval.set(JS::NullValue());
const auto notLost =
mNotLost; // Hold a strong-ref to prevent LoseContext=>UAF.
if (!notLost) return;
const auto& inProcessContext = notLost->inProcess;
Maybe<std::vector<int>> maybe;
if (inProcessContext) {
maybe = inProcessContext->GetInternalformatParameter(target, internalformat,
pname);
} else {
MOZ_ASSERT_UNREACHABLE("TODO: Remote GetInternalformatParameter");
}
auto maybe =
Run<RPROC(GetInternalformatParameter)>(target, internalformat, pname);
if (!maybe) {
return;
}
@ -2835,15 +2786,7 @@ void ClientWebGLContext::GetBufferSubData(GLenum target, GLintptr srcByteOffset,
}
auto view = RawBuffer<uint8_t>(byteLen, bytes);
const auto notLost =
mNotLost; // Hold a strong-ref to prevent LoseContext=>UAF.
if (!notLost) return;
const auto& inProcessContext = notLost->inProcess;
if (inProcessContext) {
inProcessContext->GetBufferSubData(target, srcByteOffset, view);
} else {
MOZ_ASSERT_UNREACHABLE("TODO: Remote GetBufferSubData");
}
Run<RPROC(GetBufferSubData)>(target, srcByteOffset, view);
}
////
@ -3591,18 +3534,10 @@ void ClientWebGLContext::TexImage(uint8_t funcDims, GLenum imageTarget,
}
}
const auto notLost =
mNotLost; // Hold a strong-ref to prevent LoseContext=>UAF.
if (!notLost) return;
const auto& inProcessContext = notLost->inProcess;
Maybe<std::vector<int>> maybe;
if (inProcessContext) {
inProcessContext->TexImage(imageTarget, static_cast<uint32_t>(level),
respecFormat, CastUvec3(offset), CastUvec3(size),
pi, src, *GetCanvas());
} else {
MOZ_ASSERT_UNREACHABLE("TODO: Remote GetInternalformatParameter");
}
// TODO: Convert TexImageSource into something IPC-capable.
Run<RPROC(TexImage)>(imageTarget, static_cast<uint32_t>(level), respecFormat,
CastUvec3(offset), CastUvec3(size), pi, src,
*GetCanvas());
}
void ClientWebGLContext::CompressedTexImage(bool sub, uint8_t funcDims,
@ -4088,16 +4023,7 @@ void ClientWebGLContext::ReadPixels(GLint x, GLint y, GLsizei width,
state.mPixelPackState};
const auto range = Range<uint8_t>(bytes, byteLen);
auto view = RawBufferView(range);
const auto notLost =
mNotLost; // Hold a strong-ref to prevent LoseContext=>UAF.
if (!notLost) return;
const auto& inProcessContext = notLost->inProcess;
if (inProcessContext) {
inProcessContext->ReadPixels(desc, view);
} else {
MOZ_ASSERT_UNREACHABLE("TODO: Remote ReadPixels");
}
Run<RPROC(ReadPixels)>(desc, view);
}
bool ClientWebGLContext::ReadPixels_SharedPrecheck(
@ -5385,15 +5311,7 @@ const webgl::CompileResult& ClientWebGLContext::GetCompileResult(
const webgl::LinkResult& ClientWebGLContext::GetLinkResult(
const WebGLProgramJS& prog) const {
if (prog.mResult->pending) {
const auto notLost =
mNotLost; // Hold a strong-ref to prevent LoseContext=>UAF.
if (!notLost) return *(prog.mResult);
const auto& inProcessContext = notLost->inProcess;
if (inProcessContext) {
*(prog.mResult) = inProcessContext->GetLinkResult(prog.mId);
} else {
MOZ_ASSERT_UNREACHABLE("TODO: Remote GetLinkResult");
}
*(prog.mResult) = Run<RPROC(GetLinkResult)>(prog.mId);
prog.mUniformBlockBindings.resize(
prog.mResult->active.activeUniformBlocks.size());

Просмотреть файл

@ -20,7 +20,6 @@
#include "mozilla/Logging.h"
#include "WebGLCrossProcessCommandQueue.h"
#include "WebGLCommandQueue.h"
#include <memory>
#include <unordered_map>
@ -198,8 +197,7 @@ struct RemotingData final {
//
// where 'A -> B' means "A owns B"
RefPtr<mozilla::dom::WebGLChild> mWebGLChild;
UniquePtr<ClientWebGLCommandSourceP> mCommandSourcePcq;
UniquePtr<ClientWebGLCommandSourceI> mCommandSourceIpdl;
UniquePtr<ClientWebGLCommandSource> mCommandSource;
};
struct NotLostData final {
@ -2083,9 +2081,9 @@ class ClientWebGLContext final : public nsICanvasRenderingContextInternal,
template <size_t command, typename... Args>
void DispatchAsync(Args&&... aArgs) const {
const auto& oop = *mNotLost->outOfProcess;
QueueStatus status = oop.mCommandSource->RunAsyncCommand(command,
aArgs...);
if (!IsSuccess(status)) { if (status == QueueStatus::kOOMError) {
PcqStatus status = oop.mCommandSource->RunAsyncCommand(command, aArgs...);
if (!IsSuccess(status)) {
if (status == PcqStatus::PcqOOMError) {
JsWarning("Ran out-of-memory during WebGL IPC.");
}
// Not much to do but shut down. Since this was a Pcq failure and
@ -2100,11 +2098,11 @@ class ClientWebGLContext final : public nsICanvasRenderingContextInternal,
ReturnType DispatchSync(Args&&... aArgs) const {
const auto& oop = *mNotLost->outOfProcess;
ReturnType returnValue;
QueueStatus status =
PcqStatus status =
oop.mCommandSource->RunSyncCommand(command, returnValue, aArgs...);
if (!IsSuccess(status)) {
if (status == QueueStatus::kOOMError) {
if (status == PcqStatus::PcqOOMError) {
JsWarning("Ran out-of-memory during WebGL IPC.");
}
// Not much to do but shut down. Since this was a Pcq failure and
@ -2122,7 +2120,7 @@ class ClientWebGLContext final : public nsICanvasRenderingContextInternal,
const auto status =
oop.mCommandSource->RunVoidSyncCommand(command, aArgs...);
if (!IsSuccess(status)) {
if (status == QueueStatus::kOOMError) {
if (status == PcqStatus::PcqOOMError) {
JsWarning("Ran out-of-memory during WebGL IPC.");
}
// Not much to do but shut down. Since this was a Pcq failure and

Просмотреть файл

@ -67,12 +67,7 @@ UniquePtr<HostWebGLContext> HostWebGLContext::Create(
HostWebGLContext::HostWebGLContext(OwnerData&& ownerData)
: mOwnerData(std::move(ownerData)) {
if (mOwnerData.outOfProcess) {
if (mOwnerData.outOfProcess->mCommandSinkP) {
mOwnerData.outOfProcess->mCommandSinkP->mHostContext = this;
}
if (mOwnerData.outOfProcess->mCommandSinkI) {
mOwnerData.outOfProcess->mCommandSinkI->mHostContext = this;
}
mOwnerData.outOfProcess->mCommandSink->mHostContext = this;
}
{

Просмотреть файл

@ -14,10 +14,6 @@
#include "WebGL2Context.h"
#include "WebGLFramebuffer.h"
#include "WebGLTypes.h"
#include "WebGLCommandQueue.h"
#include "WebGLCrossProcessCommandQueue.h"
#include "ProducerConsumerQueue.h"
#include "IpdlQueue.h"
#include <unordered_map>
#include <unordered_set>
@ -32,6 +28,8 @@
namespace mozilla {
class HostWebGLCommandSink;
extern LazyLogModule gWebGLBridgeLog;
namespace dom {
@ -81,8 +79,7 @@ class HostWebGLContext final : public SupportsWeakPtr<HostWebGLContext> {
struct RemotingData final {
dom::WebGLParent& mParent;
UniquePtr<HostWebGLCommandSinkP> mCommandSinkP;
UniquePtr<HostWebGLCommandSinkI> mCommandSinkI;
UniquePtr<HostWebGLCommandSink> mCommandSink;
};
struct OwnerData final {
Maybe<ClientWebGLContext*> inProcess;

Просмотреть файл

@ -1,553 +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 "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/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;
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;
};
using IpdlQueueBuffers = nsTArray<IpdlQueueBuffer>;
// Any object larger than this will be inserted into its own Shmem.
// TODO: Base this on something.
static constexpr size_t kMaxIpdlQueueArgSize = 256 * 1024;
template <typename Derived>
class AsyncProducerActor {
public:
virtual bool TransmitIpdlQueueData(bool aSendSync, IpdlQueueBuffer&& aData) {
MOZ_ASSERT(aSendSync == false);
if (mResponseBuffers) {
// 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 : *mResponseBuffers) {
if (elt.id == id) {
elt.data.AppendElements(aData.data);
return true;
}
}
mResponseBuffers->AppendElement(std::move(aData));
return true;
}
// We are not inside of a transaction. Send normally.
Derived* self = static_cast<Derived*>(this);
return self->SendTransmitIpdlQueueData(
std::forward<const IpdlQueueBuffer>(aData));
}
template <typename... Args>
bool ShouldSendSync(const Args&...) {
return false;
}
protected:
friend SyncConsumerActor<Derived>;
void SetResponseBuffers(IpdlQueueBuffers* aResponse) {
MOZ_ASSERT(!mResponseBuffers);
mResponseBuffers = aResponse;
}
void ClearResponseBuffers() {
MOZ_ASSERT(mResponseBuffers);
mResponseBuffers = nullptr;
}
IpdlQueueBuffers* mResponseBuffers = nullptr;
};
template <typename Derived>
class SyncProducerActor : public AsyncProducerActor<Derived> {
public:
bool TransmitIpdlQueueData(bool aSendSync, IpdlQueueBuffer&& aData) override {
Derived* self = static_cast<Derived*>(this);
if (mResponseBuffers || !aSendSync) {
return AsyncProducerActor<Derived>::TransmitIpdlQueueData(
aSendSync, 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(); });
return actor->RunQueue(id) ? IPC_OK() : IPC_FAIL_NO_REASON(actor);
}
};
template <typename _Actor>
class IpdlProducer final : public SupportsWeakPtr<IpdlProducer<_Actor>> {
nsTArray<uint8_t> mSerializedData;
WeakPtr<_Actor> mActor;
uint64_t mId;
public:
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(IpdlProducer<_Actor>)
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 bool toSendSync = mActor->ShouldSendSync(aArgs...);
QueueStatus status = SerializeAllArgs(std::forward<Args>(aArgs)...);
if (status != QueueStatus::kSuccess) {
return status;
}
return mActor->TransmitIpdlQueueData(
toSendSync, 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)...);
}
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) {
// TODO: Queue needs one extra byte for PCQ (fixme).
return mozilla::webgl::Marshaller::WriteObject(
mSerializedData.Elements(), mSerializedData.Length() + 1, aRead, aWrite,
arg, aArgSize);
}
inline bool NeedsSharedMemory(size_t aRequested) {
return aRequested >= kMaxIpdlQueueArgSize;
}
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 Arg, typename... Args>
size_t MinSizeofArgs(mozilla::webgl::ProducerView<SelfType>& aView) {
return aView.template MinSizeParam<Arg>() + MinSizeofArgs<Args...>(aView);
}
};
template <typename _Actor>
class IpdlConsumer final : public SupportsWeakPtr<IpdlConsumer<_Actor>> {
public:
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(IpdlConsumer<_Actor>)
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...);
}
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<typename std::remove_cv<Arg>::type*>(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);
}
static inline bool NeedsSharedMemory(size_t aRequested) {
return aRequested >= kMaxIpdlQueueArgSize;
}
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>> {
typedef mozilla::dom::IpdlProducer<Actor> paramType;
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>> {
typedef mozilla::dom::IpdlConsumer<Actor> paramType;
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> {
typedef mozilla::dom::IpdlQueueBuffer paramType;
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_

Просмотреть файл

@ -11,12 +11,6 @@ include protocol PLayerTransaction;
using mozilla::layers::CompositableHandle from "mozilla/layers/LayersTypes.h";
using mozilla::webgl::ContextLossReason from "mozilla/dom/WebGLIpdl.h";
using std::string from "ipc/IPCMessageUtils.h";
using mozilla::webgl::InitContextDesc from "mozilla/dom/WebGLIpdl.h";
using mozilla::webgl::InitContextResult from "mozilla/dom/WebGLIpdl.h";
using mozilla::HostWebGLCommandSinkP from "mozilla/dom/WebGLCrossProcessCommandQueue.h";
using mozilla::HostWebGLCommandSinkI from "mozilla/dom/WebGLCrossProcessCommandQueue.h";
using mozilla::dom::IpdlQueueBuffer from "mozilla/dom/IpdlQueue.h";
using mozilla::dom::IpdlQueueBuffers from "mozilla/dom/IpdlQueue.h";
namespace mozilla {
namespace dom {
@ -31,26 +25,17 @@ sync refcounted protocol PWebGL
manager PCompositorBridge;
parent:
sync Initialize(InitContextDesc desc, UniquePtr<HostWebGLCommandSinkP> sinkP,
UniquePtr<HostWebGLCommandSinkI> sinkI)
returns (InitContextResult res);
async __delete__();
// DLP: TODO: Does this need to be sync?
sync UpdateCompositableHandle(PLayerTransaction aLayerTrans,
CompositableHandle aHandle);
sync ExchangeIpdlQueueData(IpdlQueueBuffer aMsg) returns (IpdlQueueBuffers aResponse);
child:
async JsWarning(string text);
// Tell client that this queue needs to be shut down
async OnContextLoss(ContextLossReason aReason);
both:
async TransmitIpdlQueueData(IpdlQueueBuffer aData);
};
} // dom

Просмотреть файл

@ -9,7 +9,6 @@ namespace mozilla {
namespace webgl {
mozilla::LazyLogModule gPCQLog("pcq");
mozilla::LazyLogModule gIpdlQueueLog("ipdlqueue");
} // namespace webgl
} // namespace mozilla

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -6,7 +6,6 @@
#include "WebGLChild.h"
#include "ClientWebGLContext.h"
#include "WebGLMethodDispatcher.h"
namespace mozilla {
namespace dom {
@ -27,10 +26,5 @@ mozilla::ipc::IPCResult WebGLChild::RecvOnContextLoss(
return IPC_OK();
}
/* static */
bool WebGLChild::ShouldSendSync(size_t aCmd, ...) {
return WebGLMethodDispatcher::SyncType(aCmd) == CommandSyncType::SYNC;
}
} // namespace dom
} // namespace mozilla

Просмотреть файл

@ -9,7 +9,6 @@
#include <string>
#include "mozilla/dom/PWebGLChild.h"
#include "mozilla/dom/IpdlQueue.h"
namespace mozilla {
@ -17,24 +16,15 @@ class ClientWebGLContext;
namespace dom {
class WebGLChild final : public PWebGLChild,
public SyncProducerActor<WebGLChild>,
public AsyncConsumerActor<WebGLChild>,
public SupportsWeakPtr<WebGLChild> {
class WebGLChild final : public PWebGLChild {
public:
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(WebGLChild)
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebGLChild, override);
using OtherSideActor = WebGLParent;
ClientWebGLContext& mContext;
explicit WebGLChild(ClientWebGLContext&);
// For SyncProducerActor:
static bool ShouldSendSync(size_t aCmd, ...);
private:
friend PWebGLChild;
virtual ~WebGLChild();
public:

Просмотреть файл

@ -21,12 +21,50 @@
namespace mozilla {
using mozilla::ipc::IPDLParamTraits;
using mozilla::webgl::QueueStatus;
using mozilla::webgl::Consumer;
using mozilla::webgl::PcqStatus;
using mozilla::webgl::Producer;
using mozilla::webgl::ProducerConsumerQueue;
enum CommandResult { kSuccess, kTimeExpired, kQueueEmpty, kError };
template <typename Derived, typename SinkType>
struct MethodDispatcher;
enum CommandResult { Success, TimeExpired, QueueEmpty, Error };
enum CommandSyncType { ASYNC, SYNC };
class BasicSource {
public:
explicit BasicSource(UniquePtr<Producer>&& aProducer)
: mProducer(std::move(aProducer)) {
MOZ_ASSERT(mProducer);
}
virtual ~BasicSource() = default;
// For IPDL:
BasicSource() = default;
friend struct mozilla::ipc::IPDLParamTraits<BasicSource>;
protected:
UniquePtr<Producer> mProducer;
};
class BasicSink {
public:
explicit BasicSink(UniquePtr<Consumer>&& aConsumer)
: mConsumer(std::move(aConsumer)) {
MOZ_ASSERT(mConsumer);
}
virtual ~BasicSink() = default;
// For IPDL:
BasicSink() = default;
friend struct mozilla::ipc::IPDLParamTraits<BasicSink>;
protected:
UniquePtr<Consumer> mConsumer;
};
/**
* A CommandSource is obtained from a CommandQueue. Use it by inserting a
* command (represented by type Command) using InsertCommand, which also
@ -34,38 +72,30 @@ enum CommandSyncType { ASYNC, SYNC };
* to the CommandSink, which must understand the Command+Args combination
* to execute it.
*/
template <typename Command, typename _Source>
class CommandSource {
using Source = _Source;
template <typename Command>
class CommandSource : public BasicSource {
public:
explicit CommandSource(UniquePtr<Source>&& aSource)
: mSource(std::move(aSource)) {
MOZ_ASSERT(mSource);
explicit CommandSource(UniquePtr<Producer>&& aProducer)
: BasicSource(std::move(aProducer)) {}
template <typename... Args>
PcqStatus InsertCommand(Command aCommand, Args&&... aArgs) {
return this->mProducer->TryWaitInsert(Nothing() /* wait forever */,
aCommand, aArgs...);
}
PcqStatus InsertCommand(Command aCommand) {
return this->mProducer->TryWaitInsert(Nothing() /* wait forever */,
aCommand);
}
template <typename... Args>
QueueStatus InsertCommand(Command aCommand, Args&&... aArgs) {
return this->mSource->TryWaitInsert(Nothing() /* wait forever */, aCommand,
aArgs...);
}
QueueStatus InsertCommand(Command aCommand) {
return this->mSource->TryWaitInsert(Nothing() /* wait forever */, aCommand);
}
template <typename... Args>
QueueStatus RunCommand(Command aCommand, Args&&... aArgs) {
PcqStatus RunCommand(Command aCommand, Args&&... aArgs) {
return InsertCommand(aCommand, std::forward<Args>(aArgs)...);
}
// For IPDL:
CommandSource() = default;
protected:
friend struct IPDLParamTraits<mozilla::CommandSource<Command, Source>>;
UniquePtr<Source> mSource;
};
/**
@ -78,39 +108,36 @@ class CommandSource {
* easily run functions and methods using arguments taken from the command
* queue by calling the Dispatch methods in this class.
*/
template <typename Command, typename _Sink>
class CommandSink {
using Sink = _Sink;
template <typename Command>
class CommandSink : public BasicSink {
public:
explicit CommandSink(UniquePtr<Sink>&& aSink) : mSink(std::move(aSink)) {
MOZ_ASSERT(mSink);
}
explicit CommandSink(UniquePtr<Consumer>&& aConsumer)
: BasicSink(std::move(aConsumer)) {}
/**
* Attempts to process the next command in the queue, if one is available.
*/
CommandResult ProcessOne(const Maybe<TimeDuration>& aTimeout) {
Command command;
QueueStatus status = (aTimeout.isNothing() || aTimeout.value())
? this->mSink->TryWaitRemove(aTimeout, command)
: this->mSink->TryRemove(command);
PcqStatus status = (aTimeout.isNothing() || aTimeout.value())
? this->mConsumer->TryWaitRemove(aTimeout, command)
: this->mConsumer->TryRemove(command);
if (status == QueueStatus::kSuccess) {
if (status == PcqStatus::Success) {
if (DispatchCommand(command)) {
return CommandResult::kSuccess;
return CommandResult::Success;
}
return CommandResult::kError;
return CommandResult::Error;
}
if (status == QueueStatus::kNotReady) {
return CommandResult::kQueueEmpty;
if (status == PcqStatus::PcqNotReady) {
return CommandResult::QueueEmpty;
}
if (status == QueueStatus::kOOMError) {
if (status == PcqStatus::PcqOOMError) {
ReportOOM();
}
return CommandResult::kError;
return CommandResult::Error;
}
CommandResult ProcessOneNow() { return ProcessOne(Some(TimeDuration(0))); }
@ -125,7 +152,7 @@ class CommandSink {
CommandResult result;
do {
result = ProcessOneNow();
} while (result == CommandResult::kSuccess);
} while (result == CommandResult::Success);
return result;
}
@ -142,8 +169,7 @@ class CommandSink {
do {
result = ProcessOne(Some(aDuration - (now - start)));
now = TimeStamp::Now();
} while ((result == CommandResult::kSuccess) &&
((now - start) < aDuration));
} while ((result == CommandResult::Success) && ((now - start) < aDuration));
return result;
}
@ -198,8 +224,6 @@ class CommandSink {
}
protected:
friend struct IPDLParamTraits<mozilla::CommandSink<Command, Sink>>;
/**
* Implementations will usually be something like a big switch statement
* that calls one of the Dispatch methods in this class.
@ -213,27 +237,26 @@ class CommandSink {
virtual void ReportOOM() {}
template <typename... Args, size_t... Indices>
QueueStatus CallTryRemove(std::tuple<Args...>& aArgs,
std::index_sequence<Indices...>) {
QueueStatus status = mSink->TryRemove(std::get<Indices>(aArgs)...);
PcqStatus CallTryRemove(std::tuple<Args...>& aArgs,
std::index_sequence<Indices...>) {
PcqStatus status = mConsumer->TryRemove(std::get<Indices>(aArgs)...);
// The CommandQueue inserts the command and the args together as an atomic
// operation. We already read the command so the args must also be
// available.
MOZ_ASSERT(status != QueueStatus::kNotReady);
MOZ_ASSERT(status != PcqStatus::PcqNotReady);
return status;
}
QueueStatus CallTryRemove(std::tuple<>& aArgs,
std::make_integer_sequence<size_t, 0>) {
return QueueStatus::kSuccess;
PcqStatus CallTryRemove(std::tuple<>& aArgs,
std::make_integer_sequence<size_t, 0>) {
return PcqStatus::Success;
}
template <typename T, typename MethodType, typename... Args,
size_t... Indices,
typename ReturnType =
typename mozilla::FunctionTypeTraits<MethodType>::ReturnType>
ReturnType CallMethod(T& aObj, MethodType aMethod, std::tuple<Args...>& aArgs,
std::index_sequence<Indices...>) {
size_t... Indices, typename ReturnType>
std::result_of<MethodType> CallMethod(T& aObj, MethodType aMethod,
std::tuple<Args...>& aArgs,
std::index_sequence<Indices...>) {
return (aObj.*aMethod)(std::forward<Args>(std::get<Indices>(aArgs))...);
}
@ -246,110 +269,96 @@ class CommandSink {
template <typename... Args>
bool ReadArgs(std::tuple<Args...>& aArgs) {
QueueStatus status =
CallTryRemove(aArgs, std::index_sequence_for<Args...>{});
PcqStatus status = CallTryRemove(aArgs, std::index_sequence_for<Args...>{});
return IsSuccess(status);
}
UniquePtr<Sink> mSink;
};
enum SyncResponse : uint8_t { RESPONSE_NAK, RESPONSE_ACK };
/**
* This is the Source for a SyncCommandSink. It takes an extra queue,
* the ResponseQueue, and uses it to receive synchronous responses from
* the sink. The ResponseQueue is a regular queue, not a CommandQueue.
* This is the Source for a SyncCommandSink. It takes an extra PCQ,
* the ResponsePcq, and uses it to receive synchronous responses from
* the sink. The ResponsePcq is a regular ProducerConsumerQueue,
* not a CommandQueue.
*/
template <typename Command, typename _Source, typename _ResponseQueue>
class SyncCommandSource : public CommandSource<Command, _Source> {
template <typename Command>
class SyncCommandSource : public CommandSource<Command> {
public:
using BaseType = CommandSource<Command, _Source>;
using Source = _Source;
using ResponseQueue = _ResponseQueue;
using ResponseSink = typename ResponseQueue::Consumer;
SyncCommandSource(UniquePtr<Source>&& aSource,
UniquePtr<ResponseSink>&& aResponseSink)
: CommandSource<Command, Source>(std::move(aSource)),
mResponseSink(std::move(aResponseSink)) {}
using BaseType = CommandSource<Command>;
SyncCommandSource(UniquePtr<Producer>&& aProducer,
UniquePtr<Consumer>&& aResponseConsumer)
: CommandSource<Command>(std::move(aProducer)),
mConsumer(std::move(aResponseConsumer)) {}
template <typename... Args>
QueueStatus RunAsyncCommand(Command aCommand, Args&&... aArgs) {
PcqStatus RunAsyncCommand(Command aCommand, Args&&... aArgs) {
return this->RunCommand(aCommand, std::forward<Args>(aArgs)...);
}
template <typename... Args>
QueueStatus RunVoidSyncCommand(Command aCommand, Args&&... aArgs) {
QueueStatus status =
RunAsyncCommand(aCommand, std::forward<Args>(aArgs)...);
PcqStatus RunVoidSyncCommand(Command aCommand, Args&&... aArgs) {
PcqStatus status = RunAsyncCommand(aCommand, std::forward<Args>(aArgs)...);
return IsSuccess(status) ? this->ReadSyncResponse() : status;
}
template <typename ResultType, typename... Args>
QueueStatus RunSyncCommand(Command aCommand, ResultType& aReturn,
Args&&... aArgs) {
QueueStatus status =
PcqStatus RunSyncCommand(Command aCommand, ResultType& aReturn,
Args&&... aArgs) {
PcqStatus status =
RunVoidSyncCommand(aCommand, std::forward<Args>(aArgs)...);
return IsSuccess(status) ? this->ReadResult(aReturn) : status;
}
// for IPDL:
SyncCommandSource() = default;
friend struct mozilla::ipc::IPDLParamTraits<
SyncCommandSource<Command, Source, ResponseQueue>>;
friend struct mozilla::ipc::IPDLParamTraits<SyncCommandSource<Command>>;
protected:
QueueStatus ReadSyncResponse() {
PcqStatus ReadSyncResponse() {
SyncResponse response;
QueueStatus status =
mResponseSink->TryWaitRemove(Nothing() /* wait forever */, response);
MOZ_ASSERT(status != QueueStatus::kNotReady);
PcqStatus status =
mConsumer->TryWaitRemove(Nothing() /* wait forever */, response);
MOZ_ASSERT(status != PcqStatus::PcqNotReady);
if (IsSuccess(status) && response != RESPONSE_ACK) {
return QueueStatus::kFatalError;
return PcqStatus::PcqFatalError;
}
return status;
}
template <typename T>
QueueStatus ReadResult(T& aResult) {
QueueStatus status = mResponseSink->TryRemove(aResult);
PcqStatus ReadResult(T& aResult) {
PcqStatus status = mConsumer->TryRemove(aResult);
// The Sink posts the response code and result as an atomic transaction. We
// already read the response code so the result must be available.
MOZ_ASSERT(status != QueueStatus::kNotReady);
MOZ_ASSERT(status != PcqStatus::PcqNotReady);
return status;
}
UniquePtr<ResponseSink> mResponseSink;
UniquePtr<Consumer> mConsumer;
};
/**
* This is the Sink for a SyncCommandSource. It takes an extra queue, the
* ResponseQueue, and uses it to issue synchronous responses to the client.
* This is the Sink for a SyncCommandSource. It takes an extra PCQ, the
* ResponsePcq, and uses it to issue synchronous responses to the client.
* Subclasses can use the DispatchSync methods in this class in their
* DispatchCommand implementations.
* The ResponseQueue is not a CommandQueue.
* The ResponsePcq is not a CommandQueue.
*/
template <typename Command, typename _Sink, typename _ResponseQueue>
class SyncCommandSink : public CommandSink<Command, _Sink> {
using BaseType = CommandSink<Command, _Sink>;
using ResponseQueue = _ResponseQueue;
using Sink = _Sink;
using ResponseSource = typename ResponseQueue::Producer;
template <typename Command>
class SyncCommandSink : public CommandSink<Command> {
using BaseType = CommandSink<Command>;
public:
SyncCommandSink(UniquePtr<Sink>&& aSink,
UniquePtr<ResponseSource>&& aResponseSource)
: CommandSink<Command, Sink>(std::move(aSink)),
mResponseSource(std::move(aResponseSource)) {
MOZ_ASSERT(mResponseSource);
}
SyncCommandSink(UniquePtr<Consumer>&& aConsumer,
UniquePtr<Producer>&& aResponseProducer)
: CommandSink<Command>(std::move(aConsumer)),
mProducer(std::move(aResponseProducer)) {}
// for IPDL:
SyncCommandSink() = default;
friend struct mozilla::ipc::IPDLParamTraits<
SyncCommandSink<Command, Sink, ResponseQueue>>;
friend struct mozilla::ipc::IPDLParamTraits<SyncCommandSink<Command>>;
// Places RESPONSE_ACK and the typed return value, or RESPONSE_NAK, in
// the response queue,
@ -482,7 +491,7 @@ class SyncCommandSink : public CommandSink<Command, _Sink> {
protected:
template <typename... Args>
bool WriteArgs(const Args&... aArgs) {
return IsSuccess(mResponseSource->TryInsert(aArgs...));
return IsSuccess(mProducer->TryInsert(aArgs...));
}
template <typename... Args>
@ -496,7 +505,25 @@ class SyncCommandSink : public CommandSink<Command, _Sink> {
return WriteArgs(nak);
}
UniquePtr<ResponseSource> mResponseSource;
UniquePtr<Producer> mProducer;
};
/**
* Can be used by a sink to find and execute the handler for a given commandId.
*/
template <typename Derived>
struct CommandDispatchDriver {
/**
* Find and run the command.
*/
template <size_t commandId, typename... Args>
static MOZ_ALWAYS_INLINE bool DispatchCommandHelper(size_t aId,
Args&... aArgs) {
if (commandId == aId) {
return Derived::template Dispatch<commandId>(aArgs...);
}
return Derived::template DispatchCommand<commandId + 1>(aId, aArgs...);
}
};
/**
@ -504,61 +531,48 @@ class SyncCommandSink : public CommandSink<Command, _Sink> {
* use to dispatch sync/async commands to a method via a CommandSink.
* See DECLARE_METHOD_DISPATCHER and DEFINE_METHOD_DISPATCHER.
*/
template <typename Derived>
template <typename Derived, typename _SinkType>
struct MethodDispatcher {
using SinkType = _SinkType;
template <CommandSyncType syncType>
struct DispatchMethod;
/*
// Specialization for dispatching asynchronous methods
template <CommandSyncType SyncType>
struct DispatchMethod {
template <typename MethodType, typename ObjectType>
static MOZ_ALWAYS_INLINE bool Run(SinkType& aSink, MethodType mMethod,
ObjectType& aObj) {
return aSink.DispatchMethod<SyncType>(aObj, mMethod);
}
};
// Specialization for dispatching asynchronous methods
template <>
struct DispatchMethod<CommandSyncType::ASYNC> {
template <typename MethodType, typename ObjectType, typename SinkType>
static MOZ_ALWAYS_INLINE bool Run(SinkType& aSink, MethodType mMethod,
ObjectType& aObj) {
return aSink.DispatchAsyncMethod(aObj, mMethod);
}
};
// Specialization for dispatching synchronous methods
template <>
struct DispatchMethod<CommandSyncType::SYNC> {
template <typename MethodType, typename ObjectType, typename SinkType>
static MOZ_ALWAYS_INLINE bool Run(SinkType& aSink, MethodType aMethod,
ObjectType& aObj) {
return aSink.DispatchSyncMethod(aObj, aMethod);
}
};
// Specialization for dispatching synchronous methods
template <>
struct DispatchMethod<CommandSyncType::SYNC> {
template <typename MethodType, typename ObjectType>
static MOZ_ALWAYS_INLINE bool Run(SinkType& aSink, MethodType aMethod,
ObjectType& aObj) {
return aSink.DispatchSyncMethod(aObj, aMethod);
}
};
*/
};
// Declares a MethodDispatcher with the given name and CommandSink type.
// The ObjectType is the type of the object this class will dispatch methods to.
#define DECLARE_METHOD_DISPATCHER(_DISPATCHER, _OBJECTTYPE) \
struct _DISPATCHER : public MethodDispatcher<_DISPATCHER> { \
#define DECLARE_METHOD_DISPATCHER(_DISPATCHER, _SINKTYPE, _OBJECTTYPE) \
struct _DISPATCHER : public MethodDispatcher<_DISPATCHER, _SINKTYPE> { \
using ObjectType = _OBJECTTYPE; \
template <size_t commandId> \
struct IdDispatcher { \
template <typename SinkType> \
static MOZ_ALWAYS_INLINE bool DispatchCommand(size_t aId, \
SinkType& aSink, \
ObjectType& aObj) { \
MOZ_CRASH("Impossible -- Unhandled command ID"); \
return false; \
} \
static MOZ_ALWAYS_INLINE CommandSyncType SyncType(size_t aId) { \
MOZ_ASSERT_UNREACHABLE("Impossible -- Unhandled command ID"); \
return CommandSyncType::ASYNC; \
} \
}; \
template <typename SinkType, size_t commandId = 0> \
template <size_t commandId = 0> \
static MOZ_ALWAYS_INLINE bool DispatchCommand(size_t aId, SinkType& aSink, \
ObjectType& aObj) { \
return IdDispatcher<commandId>::DispatchCommand(aId, aSink, aObj); \
} \
template <size_t commandId = 0> \
static MOZ_ALWAYS_INLINE CommandSyncType SyncType(size_t aId) { \
return IdDispatcher<commandId>::SyncType(aId); \
MOZ_ASSERT_UNREACHABLE("Unhandled command ID"); \
return false; \
} \
template <size_t commandId> \
static MOZ_ALWAYS_INLINE bool Dispatch(SinkType& aSink, ObjectType& aObj); \
template <size_t commandId> \
struct MethodInfo; \
template <size_t commandId> \
static constexpr CommandSyncType SyncType(); \
@ -570,111 +584,127 @@ struct MethodDispatcher {
// id. The handler uses a CommandSink to read parameters, call the
// given method using the given synchronization protocol, and provide
// compile-time lookup of the ID by class method.
#define DEFINE_METHOD_DISPATCHER(_DISPATCHER, _ID, _METHOD, _SYNC) \
template <> \
struct _DISPATCHER::MethodInfo<_ID> { \
using MethodType = decltype(&_METHOD); \
}; \
template <> \
constexpr CommandSyncType _DISPATCHER::SyncType<_ID>() { \
return _SYNC; \
} \
template <> \
constexpr size_t _DISPATCHER::Id<decltype(&_METHOD), &_METHOD>() { \
return _ID; \
} \
template <> \
struct _DISPATCHER::IdDispatcher<_ID> { \
template <typename SinkType> \
static MOZ_ALWAYS_INLINE bool DispatchCommand(size_t aId, SinkType& aSink, \
ObjectType& aObj) { \
return (_ID == aId) ? DispatchMethod<_SYNC>::Run(aSink, &_METHOD, aObj) \
: _DISPATCHER::DispatchCommand<SinkType, _ID + 1>( \
aId, aSink, aObj); \
} \
static MOZ_ALWAYS_INLINE CommandSyncType SyncType(size_t aId) { \
return (_ID == aId) ? _DISPATCHER::SyncType<_ID>() \
: _DISPATCHER::SyncType<_ID + 1>(aId); \
} \
};
#define DEFINE_METHOD_DISPATCHER(_DISPATCHER, _ID, _METHOD, _SYNC) \
/* template <> \
bool _DISPATCHER::DispatchCommand<_ID>(size_t aId, SinkType & aSink, \
ObjectType & aObj) { \
return CommandDispatchDriver<_DISPATCHER>::DispatchCommandHelper<_ID>( \
aId, aSink, aObj); \
} \
template <> \
bool _DISPATCHER::Dispatch<_ID>(SinkType & aSink, ObjectType & aObj) { \
return DispatchMethod<_SYNC>::Run(aSink, &_METHOD, aObj); \
} */ \
template <> \
struct _DISPATCHER::MethodInfo<_ID> { \
using MethodType = decltype(&_METHOD); \
}; \
template <> \
constexpr CommandSyncType _DISPATCHER::SyncType<_ID>() { \
return _SYNC; \
} \
template <> \
constexpr size_t _DISPATCHER::Id<decltype(&_METHOD), &_METHOD>() { \
return _ID; \
}
namespace ipc {
template <typename T>
struct IPDLParamTraits;
template <typename Command, typename Source>
struct IPDLParamTraits<mozilla::CommandSource<Command, Source>> {
template <>
struct IPDLParamTraits<mozilla::BasicSource> {
public:
typedef mozilla::CommandSource<Command, Source> paramType;
typedef mozilla::BasicSource paramType;
static void Write(IPC::Message* aMsg, IProtocol* aActor,
const paramType& aParam) {
WriteIPDLParam(aMsg, aActor, aParam.mSource);
MOZ_ASSERT(aParam.mProducer);
WriteIPDLParam(aMsg, aActor, *aParam.mProducer.get());
}
static bool Read(const IPC::Message* aMsg, PickleIterator* aIter,
IProtocol* aActor, paramType* aResult) {
return ReadIPDLParam(aMsg, aIter, aActor, &aResult->mSource);
Producer* producer = new Producer;
bool ret = ReadIPDLParam(aMsg, aIter, aActor, producer);
aResult->mProducer.reset(producer);
return ret;
}
};
template <typename Command, typename Sink>
struct IPDLParamTraits<mozilla::CommandSink<Command, Sink>> {
template <>
struct IPDLParamTraits<mozilla::BasicSink> {
public:
typedef mozilla::CommandSink<Command, Sink> paramType;
typedef mozilla::BasicSink paramType;
static void Write(IPC::Message* aMsg, IProtocol* aActor,
const paramType& aParam) {
WriteIPDLParam(aMsg, aActor, aParam.mSink);
MOZ_ASSERT(aParam.mConsumer);
WriteIPDLParam(aMsg, aActor, *aParam.mConsumer.get());
}
static bool Read(const IPC::Message* aMsg, PickleIterator* aIter,
IProtocol* aActor, paramType* aResult) {
return ReadIPDLParam(aMsg, aIter, aActor, &aResult->mSink);
Consumer* consumer = new Consumer;
bool ret = ReadIPDLParam(aMsg, aIter, aActor, consumer);
aResult->mConsumer.reset(consumer);
return ret;
}
};
template <typename Command, typename Source, typename ResponseQueue>
struct IPDLParamTraits<
mozilla::SyncCommandSource<Command, Source, ResponseQueue>>
: public IPDLParamTraits<mozilla::CommandSource<Command, Source>> {
template <typename Command>
struct IPDLParamTraits<mozilla::CommandSource<Command>>
: public IPDLParamTraits<mozilla::BasicSource> {
public:
typedef mozilla::SyncCommandSource<Command, Source, ResponseQueue> paramType;
typedef mozilla::CommandSource<Command> paramType;
};
template <typename Command>
struct IPDLParamTraits<mozilla::CommandSink<Command>>
: public IPDLParamTraits<mozilla::BasicSink> {
public:
typedef mozilla::CommandSink<Command> paramType;
};
template <typename Command>
struct IPDLParamTraits<mozilla::SyncCommandSource<Command>>
: public IPDLParamTraits<mozilla::CommandSource<Command>> {
public:
typedef mozilla::SyncCommandSource<Command> paramType;
typedef typename paramType::BaseType paramBaseType;
static void Write(IPC::Message* aMsg, IProtocol* aActor,
const paramType& aParam) {
WriteIPDLParam(aMsg, aActor, static_cast<const paramBaseType&>(aParam));
WriteIPDLParam(aMsg, aActor, aParam.mResponseSink);
WriteIPDLParam(aMsg, aActor, aParam.mConsumer);
}
static bool Read(const IPC::Message* aMsg, PickleIterator* aIter,
IProtocol* aActor, paramType* aParam) {
bool result =
ReadIPDLParam(aMsg, aIter, aActor, static_cast<paramBaseType*>(aParam));
return result && ReadIPDLParam(aMsg, aIter, aActor, &aParam->mResponseSink);
return result && ReadIPDLParam(aMsg, aIter, aActor, &aParam->mConsumer);
}
};
template <typename Command, typename Sink, typename ResponseQueue>
struct IPDLParamTraits<mozilla::SyncCommandSink<Command, Sink, ResponseQueue>>
: public IPDLParamTraits<mozilla::CommandSink<Command, Sink>> {
template <typename Command>
struct IPDLParamTraits<mozilla::SyncCommandSink<Command>>
: public IPDLParamTraits<mozilla::CommandSink<Command>> {
public:
typedef mozilla::SyncCommandSink<Command, Sink, ResponseQueue> paramType;
typedef mozilla::SyncCommandSink<Command> paramType;
typedef typename paramType::BaseType paramBaseType;
static void Write(IPC::Message* aMsg, IProtocol* aActor,
const paramType& aParam) {
WriteIPDLParam(aMsg, aActor, static_cast<const paramBaseType&>(aParam));
WriteIPDLParam(aMsg, aActor, aParam.mResponseSource);
WriteIPDLParam(aMsg, aActor, aParam.mProducer);
}
static bool Read(const IPC::Message* aMsg, PickleIterator* aIter,
IProtocol* aActor, paramType* aParam) {
bool result =
ReadIPDLParam(aMsg, aIter, aActor, static_cast<paramBaseType*>(aParam));
return result &&
ReadIPDLParam(aMsg, aIter, aActor, &aParam->mResponseSource);
return result && ReadIPDLParam(aMsg, aIter, aActor, &aParam->mProducer);
}
};

Просмотреть файл

@ -8,14 +8,12 @@
namespace mozilla {
#if 0
bool HostWebGLCommandSink<Consumer, Queue>::DispatchCommand(size_t command) {
bool HostWebGLCommandSink::DispatchCommand(size_t command) {
if (!mHostContext) {
return false;
}
return WebGLMethodDispatcher::DispatchCommand(command, *this, *mHostContext);
}
#endif
} // namespace mozilla

Просмотреть файл

@ -7,16 +7,9 @@
#define WEBGLCROSSPROCESSCOMMANDQUEUE_H_
#include "mozilla/dom/WebGLCommandQueue.h"
#include "ProducerConsumerQueue.h"
#include "IpdlQueue.h"
namespace mozilla {
namespace dom {
class WebGLParent;
class WebGLChild;
} // namespace dom
namespace layers {
class PCompositorBridgeParent;
}
@ -28,9 +21,7 @@ using mozilla::webgl::ProducerConsumerQueue;
/**
* The source for the WebGL Command Queue.
*/
using ClientWebGLCommandSourceP =
SyncCommandSource<size_t, mozilla::webgl::PcqProducer,
mozilla::webgl::ProducerConsumerQueue>;
using ClientWebGLCommandSource = SyncCommandSource<size_t>;
/**
* The sink for the WebGL Command Queue. This object is created in the client
@ -38,56 +29,30 @@ using ClientWebGLCommandSourceP =
* then uses for executing methods. Add new commands to DispatchCommand using
* the WEBGL_SYNC_COMMAND and WEBGL_ASYNC_COMMAND macros.
*/
template <typename Consumer, typename Queue>
class HostWebGLCommandSink final
: public SyncCommandSink<size_t, Consumer, Queue> {
class HostWebGLCommandSink : public SyncCommandSink<size_t> {
public:
HostWebGLCommandSink(UniquePtr<Consumer>&& aConsumer,
UniquePtr<typename Queue::Producer>&& aResponseProducer)
: SyncCommandSink<size_t, Consumer, Queue>(
std::move(aConsumer), std::move(aResponseProducer)) {}
UniquePtr<Producer>&& aResponseProducer)
: SyncCommandSink(std::move(aConsumer), std::move(aResponseProducer)) {}
HostWebGLContext* mHostContext = nullptr;
// For IPDL:
HostWebGLCommandSink() = default;
protected:
// For IPDL:
friend struct mozilla::ipc::IPDLParamTraits<HostWebGLCommandSink>;
friend class mozilla::layers::PCompositorBridgeParent;
HostWebGLCommandSink() = default;
bool DispatchCommand(size_t command) override {
MOZ_CRASH("TODO:");
return false;
}
bool DispatchCommand(size_t command) override;
};
using HostWebGLCommandSinkP =
HostWebGLCommandSink<mozilla::webgl::PcqConsumer,
mozilla::webgl::ProducerConsumerQueue>;
using IpdlWebGLCommandQueue =
mozilla::dom::IpdlQueue<mozilla::dom::WebGLChild,
mozilla::dom::WebGLParent>;
using IpdlWebGLResponseQueue =
mozilla::dom::IpdlQueue<mozilla::dom::WebGLParent,
mozilla::dom::WebGLChild>;
using ClientWebGLCommandSourceI =
SyncCommandSource<size_t, typename IpdlWebGLCommandQueue::Producer,
IpdlWebGLResponseQueue>;
using HostWebGLCommandSinkI =
HostWebGLCommandSink<typename IpdlWebGLCommandQueue::Consumer,
IpdlWebGLResponseQueue>;
namespace ipc {
template <typename Consumer, typename Queue>
struct IPDLParamTraits<mozilla::HostWebGLCommandSink<Consumer, Queue>>
: public IPDLParamTraits<
mozilla::SyncCommandSink<size_t, Consumer, Queue>> {
template <>
struct IPDLParamTraits<mozilla::HostWebGLCommandSink>
: public IPDLParamTraits<mozilla::SyncCommandSink<size_t>> {
public:
typedef mozilla::HostWebGLCommandSink<Consumer, Queue> paramType;
typedef mozilla::HostWebGLCommandSink paramType;
};
} // namespace ipc

Просмотреть файл

@ -9,13 +9,14 @@
#include "TexUnpackBlob.h"
#include "WebGLCrossProcessCommandQueue.h"
#include "HostWebGLContext.h"
#include "WebGLQueueParamTraits.h"
#include "WebGLPcqParamTraits.h"
namespace mozilla {
// The WebGLMethodDispatcher will dispatch commands read from the
// HostWebGLCommandSink and issue them to a given HostWebGLContext.
DECLARE_METHOD_DISPATCHER(WebGLMethodDispatcher, HostWebGLContext)
DECLARE_METHOD_DISPATCHER(WebGLMethodDispatcher, HostWebGLCommandSink,
HostWebGLContext)
// Defines each method the WebGLMethodDispatcher handles. The COUNTER value
// is used as a cross-process ID for each of the methods.
@ -52,14 +53,14 @@ DEFINE_ASYNC(HostWebGLContext::DeleteTransformFeedback)
DEFINE_ASYNC(HostWebGLContext::DeleteVertexArray)
DEFINE_ASYNC(HostWebGLContext::ClearVRFrame)
// DEFINE_SYNC(HostWebGLContext::GetVRFrame)
DEFINE_SYNC(HostWebGLContext::GetVRFrame)
DEFINE_ASYNC(HostWebGLContext::Disable)
DEFINE_ASYNC(HostWebGLContext::Enable)
DEFINE_ASYNC(HostWebGLContext::GenerateError)
DEFINE_SYNC(HostWebGLContext::GetCompileResult)
DEFINE_SYNC(HostWebGLContext::GetFragDataLocation)
// DEFINE_SYNC(HostWebGLContext::GetLinkResult)
DEFINE_SYNC(HostWebGLContext::GetLinkResult)
DEFINE_SYNC(HostWebGLContext::InitializeCanvasRenderer)
DEFINE_SYNC(HostWebGLContext::IsEnabled)
DEFINE_ASYNC(HostWebGLContext::Resize)
@ -113,21 +114,21 @@ DEFINE_ASYNC(HostWebGLContext::Viewport)
DEFINE_ASYNC(HostWebGLContext::BindBuffer)
DEFINE_ASYNC(HostWebGLContext::BindBufferRange)
DEFINE_ASYNC(HostWebGLContext::CopyBufferSubData)
// DEFINE_ASYNC(HostWebGLContext::GetBufferSubData)
DEFINE_ASYNC(HostWebGLContext::GetBufferSubData)
DEFINE_ASYNC(HostWebGLContext::BufferData)
DEFINE_ASYNC(HostWebGLContext::BufferSubData)
DEFINE_ASYNC(HostWebGLContext::BlitFramebuffer)
DEFINE_ASYNC(HostWebGLContext::InvalidateFramebuffer)
DEFINE_ASYNC(HostWebGLContext::InvalidateSubFramebuffer)
DEFINE_ASYNC(HostWebGLContext::ReadBuffer)
// DEFINE_SYNC(HostWebGLContext::GetInternalformatParameter)
DEFINE_SYNC(HostWebGLContext::GetInternalformatParameter)
DEFINE_ASYNC(HostWebGLContext::RenderbufferStorageMultisample)
DEFINE_ASYNC(HostWebGLContext::ActiveTexture)
DEFINE_ASYNC(HostWebGLContext::BindTexture)
DEFINE_ASYNC(HostWebGLContext::GenerateMipmap)
DEFINE_ASYNC(HostWebGLContext::CopyTexImage)
DEFINE_ASYNC(HostWebGLContext::TexStorage)
// DEFINE_ASYNC(HostWebGLContext::TexImage)
DEFINE_ASYNC(HostWebGLContext::TexImage)
DEFINE_ASYNC(HostWebGLContext::CompressedTexImage)
DEFINE_SYNC(HostWebGLContext::GetTexParameter)
DEFINE_ASYNC(HostWebGLContext::TexParameter_base)
@ -144,7 +145,7 @@ DEFINE_SYNC(HostWebGLContext::GetVertexAttrib)
DEFINE_ASYNC(HostWebGLContext::VertexAttribPointer)
DEFINE_ASYNC(HostWebGLContext::ClearBufferTv)
DEFINE_ASYNC(HostWebGLContext::ClearBufferfi)
// DEFINE_SYNC(HostWebGLContext::ReadPixels)
DEFINE_SYNC(HostWebGLContext::ReadPixels)
DEFINE_ASYNC(HostWebGLContext::ReadPixelsPbo)
DEFINE_ASYNC(HostWebGLContext::BindSampler)
DEFINE_ASYNC(HostWebGLContext::SamplerParameteri)

Просмотреть файл

@ -5,7 +5,6 @@
#include "WebGLParent.h"
#include "WebGLChild.h"
#include "mozilla/dom/WebGLCrossProcessCommandQueue.h"
#include "mozilla/layers/LayerTransactionParent.h"
#include "mozilla/layers/TextureClientSharedSurface.h"
@ -15,31 +14,30 @@ namespace mozilla {
namespace dom {
mozilla::ipc::IPCResult WebGLParent::RecvInitialize(
const webgl::InitContextDesc& desc,
UniquePtr<HostWebGLCommandSinkP>&& aSinkP,
UniquePtr<HostWebGLCommandSinkI>&& aSinkI,
webgl::InitContextResult* const out) {
/* static */
RefPtr<WebGLParent> WebGLParent::Create(const webgl::InitContextDesc& desc,
webgl::InitContextResult* const out) {
RefPtr<WebGLParent> parent = new WebGLParent;
auto remotingData = Some(HostWebGLContext::RemotingData{
*this, {}, // std::move(commandSink),
*parent, {}, // std::move(commandSink),
});
mHost = HostWebGLContext::Create(
parent->mHost = HostWebGLContext::Create(
{
{},
std::move(remotingData),
},
desc, out);
if (!mHost) {
return IPC_FAIL(this, "Failed to create HostWebGLContext");
if (!parent->mHost) {
WEBGL_BRIDGE_LOGE("Failed to create HostWebGLContext");
return nullptr;
}
if (!BeginCommandQueueDrain()) {
return IPC_FAIL(this, "Failed to start WebGL command queue drain");
if (!parent->BeginCommandQueueDrain()) {
WEBGL_BRIDGE_LOGE("Failed to start WebGL command queue drain");
return nullptr;
}
return IPC_OK();
return parent;
}
WebGLParent::WebGLParent() = default;

Просмотреть файл

@ -9,10 +9,10 @@
#include "mozilla/GfxMessageUtils.h"
#include "mozilla/dom/PWebGLParent.h"
#include "mozilla/WeakPtr.h"
#include "mozilla/dom/IpdlQueue.h"
namespace mozilla {
class HostWebGLCommandSink;
class HostWebGLContext;
namespace layers {
@ -21,30 +21,21 @@ class SharedSurfaceTextureClient;
namespace dom {
class WebGLParent : public PWebGLParent,
public AsyncProducerActor<WebGLParent>,
public SyncConsumerActor<WebGLParent>,
public SupportsWeakPtr<WebGLParent> {
class WebGLParent final : public PWebGLParent,
public SupportsWeakPtr<WebGLParent> {
friend PWebGLParent;
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebGLParent, override);
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(WebGLParent)
using OtherSideActor = WebGLChild;
mozilla::ipc::IPCResult RecvInitialize(
const webgl::InitContextDesc&, UniquePtr<HostWebGLCommandSinkP>&& aSinkP,
UniquePtr<HostWebGLCommandSinkI>&& aSinkI, webgl::InitContextResult* out);
static RefPtr<WebGLParent> Create(const webgl::InitContextDesc&,
webgl::InitContextResult* out);
RefPtr<layers::SharedSurfaceTextureClient> GetVRFrame(webgl::ObjectId);
// Drain the command queue now. Used by synchronous IpdlQueue consumers.
bool RunQueue(uint64_t) { return RunCommandQueue(); }
// For IPDL:
WebGLParent();
private:
WebGLParent();
~WebGLParent();
bool BeginCommandQueueDrain();

Просмотреть файл

@ -3,8 +3,8 @@
* 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 WEBGLQUEUEPARAMTRAITS_H_
#define WEBGLQUEUEPARAMTRAITS_H_
#ifndef WEBGLPCQPARAMTRAITS_H_
#define WEBGLPCQPARAMTRAITS_H_
#include <type_traits>
@ -17,7 +17,7 @@ namespace mozilla {
namespace webgl {
template <typename T>
struct QueueParamTraits;
struct PcqParamTraits;
template <>
struct IsTriviallySerializable<FloatOrInt> : std::true_type {};
@ -56,21 +56,12 @@ struct IsTriviallySerializable<avec3<T>> : std::true_type {};
template <>
struct IsTriviallySerializable<webgl::TexUnpackBlob> : std::true_type {};
template <>
struct IsTriviallySerializable<webgl::TypedQuad> : std::true_type {};
template <>
struct IsTriviallySerializable<webgl::VertAttribPointerDesc> : std::true_type {
};
template <>
struct IsTriviallySerializable<webgl::ReadPixelsDesc> : std::true_type {};
/*
template <>
struct QueueParamTraits<WebGLActiveInfo> {
struct PcqParamTraits<WebGLActiveInfo> {
using ParamType = WebGLActiveInfo;
static QueueStatus Write(ProducerView& aProducerView, const ParamType& aArg) {
static PcqStatus Write(ProducerView& aProducerView, const ParamType& aArg) {
aProducerView.WriteParam(aArg.mElemCount);
aProducerView.WriteParam(aArg.mElemType);
aProducerView.WriteParam(aArg.mBaseUserName);
@ -80,7 +71,7 @@ struct QueueParamTraits<WebGLActiveInfo> {
return aProducerView.WriteParam(aArg.mBaseType);
}
static QueueStatus Read(ConsumerView& aConsumerView, ParamType* aArg) {
static PcqStatus Read(ConsumerView& aConsumerView, ParamType* aArg) {
aConsumerView.ReadParam(aArg ? &aArg->mElemCount : nullptr);
aConsumerView.ReadParam(aArg ? &aArg->mElemType : nullptr);
aConsumerView.ReadParam(aArg ? &aArg->mBaseUserName : nullptr);
@ -103,23 +94,21 @@ struct QueueParamTraits<WebGLActiveInfo> {
};
*/
template <typename T>
struct QueueParamTraits<RawBuffer<T>> {
struct PcqParamTraits<RawBuffer<T>> {
using ParamType = RawBuffer<T>;
template <typename U>
static QueueStatus Write(ProducerView<U>& aProducerView,
const ParamType& aArg) {
static PcqStatus Write(ProducerView& aProducerView, const ParamType& aArg) {
aProducerView.WriteParam(aArg.mLength);
return (aArg.mLength > 0)
? aProducerView.Write(aArg.mData, aArg.mLength * sizeof(T))
: aProducerView.GetStatus();
: aProducerView.Status();
}
template <typename U, typename ElementType = typename std::remove_cv_t<
typename ParamType::ElementType>>
static QueueStatus Read(ConsumerView<U>& aConsumerView, ParamType* aArg) {
template <
typename ElementType = std::remove_cv_t<typename ParamType::ElementType>>
static PcqStatus Read(ConsumerView& aConsumerView, ParamType* aArg) {
size_t len;
QueueStatus status = aConsumerView.ReadParam(&len);
PcqStatus status = aConsumerView.ReadParam(&len);
if (!status) {
return status;
}
@ -129,7 +118,7 @@ struct QueueParamTraits<RawBuffer<T>> {
aArg->mLength = 0;
aArg->mData = nullptr;
}
return QueueStatus::kSuccess;
return PcqStatus::Success;
}
if (!aArg) {
@ -137,17 +126,17 @@ struct QueueParamTraits<RawBuffer<T>> {
}
struct RawBufferReadMatcher {
QueueStatus operator()(RefPtr<mozilla::ipc::SharedMemoryBasic>& smem) {
PcqStatus operator()(RefPtr<mozilla::ipc::SharedMemoryBasic>& smem) {
if (!smem) {
return QueueStatus::kFatalError;
return PcqStatus::PcqFatalError;
}
mArg->mSmem = smem;
mArg->mData = static_cast<ElementType*>(smem->memory());
mArg->mLength = mLength;
mArg->mOwnsData = false;
return QueueStatus::kSuccess;
return PcqStatus::Success;
}
QueueStatus operator()() {
PcqStatus operator()() {
mArg->mSmem = nullptr;
ElementType* buf = new ElementType[mLength];
mArg->mData = buf;
@ -156,7 +145,7 @@ struct QueueParamTraits<RawBuffer<T>> {
return mConsumerView.Read(buf, mLength * sizeof(T));
}
ConsumerView<U>& mConsumerView;
ConsumerView& mConsumerView;
ParamType* mArg;
size_t mLength;
};
@ -176,16 +165,16 @@ struct QueueParamTraits<RawBuffer<T>> {
enum TexUnpackTypes : uint8_t { Bytes, Surface, Image, Pbo };
template <>
struct QueueParamTraits<webgl::TexUnpackBytes> {
struct PcqParamTraits<webgl::TexUnpackBytes> {
using ParamType = webgl::TexUnpackBytes;
static QueueStatus Write(ProducerView& aProducerView, const ParamType& aArg) {
static PcqStatus Write(ProducerView& aProducerView, const ParamType& aArg) {
// Write TexUnpackBlob base class, then the RawBuffer.
aProducerView.WriteParam(static_cast<const webgl::TexUnpackBlob&>(aArg));
return aProducerView.WriteParam(aArg.mPtr);
}
static QueueStatus Read(ConsumerView& aConsumerView, ParamType* aArg) {
static PcqStatus Read(ConsumerView& aConsumerView, ParamType* aArg) {
// Read TexUnpackBlob base class, then the RawBuffer.
aConsumerView.ReadParam(static_cast<webgl::TexUnpackBlob*>(aArg));
return aConsumerView.ReadParam(aArg ? &aArg->mPtr : nullptr);
@ -199,10 +188,10 @@ struct QueueParamTraits<webgl::TexUnpackBytes> {
};
template <>
struct QueueParamTraits<webgl::TexUnpackSurface> {
struct PcqParamTraits<webgl::TexUnpackSurface> {
using ParamType = webgl::TexUnpackSurface;
static QueueStatus Write(ProducerView& aProducerView, const ParamType& aArg) {
static PcqStatus Write(ProducerView& aProducerView, const ParamType& aArg) {
aProducerView.WriteParam(static_cast<const webgl::TexUnpackBlob&>(aArg));
aProducerView.WriteParam(aArg.mSize);
aProducerView.WriteParam(aArg.mFormat);
@ -210,7 +199,7 @@ struct QueueParamTraits<webgl::TexUnpackSurface> {
return aProducerView.WriteParam(aArg.mStride);
}
static QueueStatus Read(ConsumerView& aConsumerView, ParamType* aArg) {
static PcqStatus Read(ConsumerView& aConsumerView, ParamType* aArg) {
aConsumerView.ReadParam(static_cast<webgl::TexUnpackBlob*>(aArg));
aConsumerView.ReadParam(aArg ? &aArg->mSize : nullptr);
aConsumerView.ReadParam(aArg ? &aArg->mFormat : nullptr);
@ -228,28 +217,28 @@ struct QueueParamTraits<webgl::TexUnpackSurface> {
}
};
// Specialization of QueueParamTraits that adapts the TexUnpack type in order to
// Specialization of PcqParamTraits that adapts the TexUnpack type in order to
// efficiently convert types. For example, a TexUnpackSurface may deserialize
// as a TexUnpackBytes.
template <>
struct QueueParamTraits<WebGLTexUnpackVariant> {
struct PcqParamTraits<WebGLTexUnpackVariant> {
using ParamType = WebGLTexUnpackVariant;
static QueueStatus Write(ProducerView& aProducerView, const ParamType& aArg) {
static PcqStatus Write(ProducerView& aProducerView, const ParamType& aArg) {
struct TexUnpackWriteMatcher {
QueueStatus operator()(const UniquePtr<webgl::TexUnpackBytes>& x) {
PcqStatus operator()(const UniquePtr<webgl::TexUnpackBytes>& x) {
mProducerView.WriteParam(TexUnpackTypes::Bytes);
return mProducerView.WriteParam(x);
}
QueueStatus operator()(const UniquePtr<webgl::TexUnpackSurface>& x) {
PcqStatus operator()(const UniquePtr<webgl::TexUnpackSurface>& x) {
mProducerView.WriteParam(TexUnpackTypes::Surface);
return mProducerView.WriteParam(x);
}
QueueStatus operator()(const UniquePtr<webgl::TexUnpackImage>& x) {
PcqStatus operator()(const UniquePtr<webgl::TexUnpackImage>& x) {
MOZ_ASSERT_UNREACHABLE("TODO:");
return QueueStatus::kFatalError;
return PcqStatus::PcqFatalError;
}
QueueStatus operator()(const WebGLTexPboOffset& x) {
PcqStatus operator()(const WebGLTexPboOffset& x) {
mProducerView.WriteParam(TexUnpackTypes::Pbo);
return mProducerView.WriteParam(x);
}
@ -258,14 +247,14 @@ struct QueueParamTraits<WebGLTexUnpackVariant> {
return aArg.match(TexUnpackWriteMatcher{aProducerView});
}
static QueueStatus Read(ConsumerView& aConsumerView, ParamType* aArg) {
static PcqStatus Read(ConsumerView& aConsumerView, ParamType* aArg) {
if (!aArg) {
// Not a great estimate but we can't do much better.
return aConsumerView.template ReadParam<TexUnpackTypes>();
}
TexUnpackTypes unpackType;
if (!aConsumerView.ReadParam(&unpackType)) {
return aConsumerView.GetStatus();
return aConsumerView.Status();
}
switch (unpackType) {
case TexUnpackTypes::Bytes:
@ -278,13 +267,13 @@ struct QueueParamTraits<WebGLTexUnpackVariant> {
&aArg->as<UniquePtr<webgl::TexUnpackSurface>>());
case TexUnpackTypes::Image:
MOZ_ASSERT_UNREACHABLE("TODO:");
return QueueStatus::kFatalError;
return PcqStatus::PcqFatalError;
case TexUnpackTypes::Pbo:
*aArg = AsVariant(WebGLTexPboOffset());
return aConsumerView.ReadParam(&aArg->as<WebGLTexPboOffset>());
}
MOZ_ASSERT_UNREACHABLE("Illegal texture unpack type");
return QueueStatus::kFatalError;
return PcqStatus::PcqFatalError;
}
template <typename View>
@ -315,23 +304,20 @@ struct QueueParamTraits<WebGLTexUnpackVariant> {
};
*/
template <>
struct QueueParamTraits<webgl::ContextLossReason> {
struct PcqParamTraits<webgl::ContextLossReason> {
using ParamType = webgl::ContextLossReason;
template <typename U>
static QueueStatus Write(ProducerView<U>& aProducerView,
const ParamType& aArg) {
static PcqStatus Write(ProducerView& aProducerView, const ParamType& aArg) {
return aProducerView.WriteParam(static_cast<uint8_t>(aArg));
}
template <typename U>
static QueueStatus Read(ConsumerView<U>& aConsumerView, ParamType* aArg) {
static PcqStatus Read(ConsumerView& aConsumerView, ParamType* aArg) {
uint8_t val;
auto status = aConsumerView.ReadParam(&val);
if (!status) return status;
if (!ReadContextLossReason(val, aArg)) {
MOZ_ASSERT_UNREACHABLE("Invalid ContextLossReason");
return QueueStatus::kFatalError;
return PcqStatus::PcqFatalError;
}
return status;
}
@ -343,11 +329,10 @@ struct QueueParamTraits<webgl::ContextLossReason> {
};
template <typename V, typename E>
struct QueueParamTraits<Result<V, E>> {
struct PcqParamTraits<Result<V, E>> {
using T = Result<V, E>;
template <typename U>
static QueueStatus Write(ProducerView<U>& aProducerView, const T& aArg) {
static PcqStatus Write(ProducerView& aProducerView, const T& aArg) {
const auto ok = aArg.isOk();
auto status = aProducerView.WriteParam(ok);
if (!status) return status;
@ -359,8 +344,7 @@ struct QueueParamTraits<Result<V, E>> {
return status;
}
template <typename U>
static QueueStatus Read(ConsumerView<U>& aConsumerView, T* const aArg) {
static PcqStatus Read(ConsumerView& aConsumerView, T* const aArg) {
bool ok;
auto status = aConsumerView.ReadParam(&ok);
if (!status) return status;
@ -393,26 +377,24 @@ struct QueueParamTraits<Result<V, E>> {
};
template <>
struct QueueParamTraits<std::string> {
struct PcqParamTraits<std::string> {
using T = std::string;
template <typename U>
static QueueStatus Write(ProducerView<U>& aProducerView, const T& aArg) {
static PcqStatus Write(ProducerView& aProducerView, const T& aArg) {
auto status = aProducerView.WriteParam(aArg.size());
if (!status) return status;
status = aProducerView.Write(aArg.data(), aArg.size());
return status;
}
template <typename U>
static QueueStatus Read(ConsumerView<U>& aConsumerView, T* const aArg) {
static PcqStatus Read(ConsumerView& aConsumerView, T* const aArg) {
size_t size;
auto status = aConsumerView.ReadParam(&size);
if (!status) return status;
const UniqueBuffer temp = malloc(size);
const auto dest = static_cast<char*>(temp.get());
if (!dest) return QueueStatus::kFatalError;
if (!dest) return PcqStatus::PcqFatalError;
status = aConsumerView.Read(dest, size);
if (aArg) {
@ -432,19 +414,17 @@ struct QueueParamTraits<std::string> {
};
template <typename U>
struct QueueParamTraits<std::vector<U>> {
using T = std::vector<U>;
struct PcqParamTraits<std::vector<U>> {
using T = std::string;
template <typename V>
static QueueStatus Write(ProducerView<V>& aProducerView, const T& aArg) {
static PcqStatus Write(ProducerView& aProducerView, const T& aArg) {
auto status = aProducerView.WriteParam(aArg.size());
if (!status) return status;
status = aProducerView.Write(aArg.data(), aArg.size());
return status;
}
template <typename V>
static QueueStatus Read(ConsumerView<V>& aConsumerView, T* const aArg) {
static PcqStatus Read(ConsumerView& aConsumerView, T* const aArg) {
MOZ_CRASH("no way to fallibly resize vectors without exceptions");
size_t size;
auto status = aConsumerView.ReadParam(&size);
@ -466,23 +446,21 @@ struct QueueParamTraits<std::vector<U>> {
};
template <>
struct QueueParamTraits<WebGLExtensionID> {
struct PcqParamTraits<WebGLExtensionID> {
using T = WebGLExtensionID;
template <typename U>
static QueueStatus Write(ProducerView<U>& aProducerView, const T& aArg) {
static PcqStatus Write(ProducerView& aProducerView, const T& aArg) {
return aProducerView.WriteParam(mozilla::EnumValue(aArg));
}
template <typename U>
static QueueStatus Read(ConsumerView<U>& aConsumerView, T* const aArg) {
QueueStatus status = QueueStatus::kSuccess;
static PcqStatus Read(ConsumerView& aConsumerView, T* const aArg) {
PcqStatus status = PcqStatus::Success;
if (aArg) {
status = aConsumerView.ReadParam(
reinterpret_cast<typename std::underlying_type<T>::type*>(aArg));
if (*aArg >= WebGLExtensionID::Max) {
MOZ_ASSERT(false);
return QueueStatus::kFatalError;
return PcqStatus::PcqFatalError;
}
}
return status;
@ -494,71 +472,7 @@ struct QueueParamTraits<WebGLExtensionID> {
}
};
template <>
struct QueueParamTraits<CompileResult> {
using T = CompileResult;
template <typename U>
static QueueStatus Write(ProducerView<U>& aProducerView, const T& aArg) {
aProducerView.WriteParam(aArg.pending);
aProducerView.WriteParam(aArg.log);
aProducerView.WriteParam(aArg.translatedSource);
return aProducerView.WriteParam(aArg.success);
}
template <typename U>
static QueueStatus Read(ConsumerView<U>& aConsumerView, T* const aArg) {
aConsumerView.ReadParam(aArg ? &aArg->pending : nullptr);
aConsumerView.ReadParam(aArg ? &aArg->log : nullptr);
aConsumerView.ReadParam(aArg ? &aArg->translatedSource : nullptr);
return aConsumerView.ReadParam(aArg ? &aArg->success : nullptr);
}
template <typename View>
static size_t MinSize(View& aView, const T* const aArg) {
return aView.MinSizeParam(aArg ? &aArg->pending : nullptr) +
aView.MinSizeParam(aArg ? &aArg->log : nullptr) +
aView.MinSizeParam(aArg ? &aArg->translatedSource : nullptr) +
aView.MinSizeParam(aArg ? &aArg->success : nullptr);
}
};
#if 0
// TODO: QueueParamTraits for LinkActiveResult and friends.
template <>
struct QueueParamTraits<LinkResult> {
using T = LinkResult;
template <typename U>
static QueueStatus Write(ProducerView<U>& aProducerView, const T& aArg) {
aProducerView.WriteParam(aArg.pending);
aProducerView.WriteParam(aArg.log);
aProducerView.WriteParam(aArg.active);
aProducerView.WriteParam(aArg.tfBufferMode);
return aProducerView.WriteParam(aArg.success);
}
template <typename U>
static QueueStatus Read(ConsumerView<U>& aConsumerView, T* const aArg) {
aConsumerView.ReadParam(aArg ? &aArg->pending : nullptr);
aConsumerView.ReadParam(aArg ? &aArg->log : nullptr);
aConsumerView.ReadParam(aArg ? &aArg->active : nullptr);
aConsumerView.ReadParam(aArg ? &aArg->tfBufferMode : nullptr);
return aConsumerView.ReadParam(aArg ? &aArg->success : nullptr);
}
template <typename View>
static size_t MinSize(View& aView, const T* const aArg) {
return aView.MinSizeParam(aArg ? &aArg->pending : nullptr) +
aView.MinSizeParam(aArg ? &aArg->log : nullptr) +
aView.MinSizeParam(aArg ? &aArg->active : nullptr) +
aView.MinSizeParam(aArg ? &aArg->tfBufferMode : nullptr) +
aView.MinSizeParam(aArg ? &aArg->success : nullptr);
}
};
#endif
} // namespace webgl
} // namespace mozilla
#endif // WEBGLQUEUEPARAMTRAITS_H_
#endif // WEBGLPCQPARAMTRAITS_H_

Просмотреть файл

@ -94,9 +94,12 @@ inline auto AutoAssertCast(const From val) {
return detail::AutoAssertCastT<From>(val);
}
namespace webgl {
namespace ipc {
template <typename T>
struct QueueParamTraits;
struct PcqParamTraits;
}
namespace webgl {
class TexUnpackBytes;
class TexUnpackImage;
class TexUnpackSurface;
@ -730,7 +733,7 @@ class RawBuffer {
// true if we should delete[] the mData on destruction
bool mOwnsData = false;
friend struct mozilla::webgl::QueueParamTraits<RawBuffer<T>>;
friend mozilla::ipc::PcqParamTraits<RawBuffer>;
public:
using ElementType = T;

Просмотреть файл

@ -58,10 +58,8 @@ EXPORTS.mozilla.dom += [
'ImageBitmapSource.h',
'ImageData.h',
'ImageUtils.h',
'IpdlQueue.h',
'OffscreenCanvas.h',
'ProducerConsumerQueue.h',
'QueueParamTraits.h',
'TextMetrics.h',
'WebGLChild.h',
'WebGLCommandQueue.h',
@ -96,7 +94,7 @@ UNIFIED_SOURCES += [
'ClientWebGLContext.cpp',
'ClientWebGLExtensions.cpp',
'HostWebGLContext.cpp',
'Queue.cpp',
'ProducerConsumerQueue.cpp',
'TexUnpackBlob.cpp',
'WebGL2Context.cpp',
'WebGL2ContextBuffers.cpp',

Просмотреть файл

@ -12,6 +12,7 @@
#include "base/message_loop.h" // for MessageLoop
#include "base/task.h" // for NewRunnableMethod, etc
#include "mozilla/StaticPrefs_layers.h"
#include "mozilla/dom/WebGLChild.h"
#include "mozilla/layers/CompositorManagerChild.h"
#include "mozilla/layers/ImageBridgeChild.h"
#include "mozilla/layers/APZChild.h"

Просмотреть файл

@ -53,6 +53,7 @@ class nsIWidget;
namespace mozilla {
class CancelableRunnable;
class HostWebGLCommandSink;
namespace dom {
class WebGLParent;
@ -302,7 +303,8 @@ class CompositorBridgeParentBase : public PCompositorBridgeParent,
return IPC_FAIL_NO_REASON(this);
}
virtual already_AddRefed<PWebGLParent> AllocPWebGLParent() = 0;
virtual already_AddRefed<PWebGLParent> AllocPWebGLParent(
const webgl::InitContextDesc&, webgl::InitContextResult* out) = 0;
bool mCanSend;
@ -692,7 +694,8 @@ class CompositorBridgeParent final : public CompositorBridgeParentBase,
WebRenderBridgeParent* GetWrBridge() { return mWrBridge; }
webgpu::WebGPUParent* GetWebGPUBridge() { return mWebGPUBridge; }
already_AddRefed<PWebGLParent> AllocPWebGLParent() override {
already_AddRefed<PWebGLParent> AllocPWebGLParent(
const webgl::InitContextDesc&, webgl::InitContextResult*) override {
MOZ_ASSERT_UNREACHABLE(
"This message is CrossProcessCompositorBridgeParent only");
return nullptr;

Просмотреть файл

@ -766,9 +766,11 @@ mozilla::ipc::IPCResult ContentCompositorBridgeParent::RecvPreferredDXGIAdapter(
}
already_AddRefed<dom::PWebGLParent>
ContentCompositorBridgeParent::AllocPWebGLParent() {
RefPtr<dom::PWebGLParent> parent = new dom::WebGLParent();
return parent.forget();
ContentCompositorBridgeParent::AllocPWebGLParent(
const webgl::InitContextDesc& aInitDesc,
webgl::InitContextResult* const out) {
RefPtr<dom::PWebGLParent> ret = dom::WebGLParent::Create(aInitDesc, out);
return ret.forget();
}
} // namespace layers

Просмотреть файл

@ -161,7 +161,8 @@ class ContentCompositorBridgeParent final : public CompositorBridgeParentBase {
return IPC_FAIL_NO_REASON(this);
}
already_AddRefed<dom::PWebGLParent> AllocPWebGLParent() override;
already_AddRefed<dom::PWebGLParent> AllocPWebGLParent(
const webgl::InitContextDesc&, webgl::InitContextResult* out) override;
// Use DidCompositeLocked if you already hold a lock on
// sIndirectLayerTreesLock; Otherwise use DidComposite, which would request

Просмотреть файл

@ -48,6 +48,8 @@ using mozilla::wr::MaybeExternalImageId from "mozilla/webrender/WebRenderTypes.h
using mozilla::layers::LayersObserverEpoch from "mozilla/layers/LayersTypes.h";
using mozilla::layers::TransactionId from "mozilla/layers/LayersTypes.h";
using struct DxgiAdapterDesc from "mozilla/D3DMessageUtils.h";
using mozilla::webgl::InitContextDesc from "mozilla/dom/WebGLIpdl.h";
using mozilla::webgl::InitContextResult from "mozilla/dom/WebGLIpdl.h";
namespace mozilla {
namespace layers {
@ -298,7 +300,9 @@ parent:
async RequestFxrOutput();
// Actor that represents one WebGL context.
async PWebGL();
// (modeled after `sync PBackgroundLSSnapshot`)
sync PWebGL(InitContextDesc desc)
returns (InitContextResult res);
child:
// Send back Compositor Frame Metrics from APZCs so tiled layers can

Просмотреть файл

@ -1213,10 +1213,8 @@ description = Synchronous ping allowing worker thread to confirm actor is create
description = Synchronous launch of a child process that in turn launches and sandboxes another process. Called on a dedicated thread and targets a dedicated process, so this shouldn't block anything.
[PWebGL::UpdateCompositableHandle]
description = Compositing WebGL is synchronous by spec. Updates to WebGL canvas contents must be updated in lockstep with other DOM updates.
[PWebGL::Initialize]
description = Initialization of WebGL contexts is synchronous by spec.
[PWebGL::ExchangeIpdlQueueData]
description = Synchronous RPC to allow WebGL to run graphics commands in compositor process and return results to be used in JS return values.
[PCompositorBridge::PWebGL]
description = Creation of WebGL contexts is synchronous by spec.
[PSocketProcess::GetTLSClientCert]
description = Synchronously get client certificate and key from parent process. Once bug 696976 has been fixed, this can be removed.

Просмотреть файл

@ -8952,12 +8952,6 @@
value: true
mirror: always
# value is 0 for PCQ, 1 for Ipdl
- name: webgl.prototype.ipc-pcq
type: uint32_t
value: 0
mirror: always
#---------------------------------------------------------------------------
# Prefs starting with "widget."
#---------------------------------------------------------------------------