зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
63b9840733
Коммит
452acadb3b
|
@ -461,15 +461,7 @@ void ClientWebGLContext::ClearVRFrame() const { Run<RPROC(ClearVRFrame)>(); }
|
||||||
|
|
||||||
RefPtr<layers::SharedSurfaceTextureClient> ClientWebGLContext::GetVRFrame(
|
RefPtr<layers::SharedSurfaceTextureClient> ClientWebGLContext::GetVRFrame(
|
||||||
const WebGLFramebufferJS* fb) const {
|
const WebGLFramebufferJS* fb) const {
|
||||||
const auto notLost =
|
return Run<RPROC(GetVRFrame)>(fb ? fb->mId : 0);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<layers::Layer> ClientWebGLContext::GetCanvasLayer(
|
already_AddRefed<layers::Layer> ClientWebGLContext::GetCanvasLayer(
|
||||||
|
@ -732,55 +724,32 @@ bool ClientWebGLContext::CreateHostContext(const uvec2& requestedSize) {
|
||||||
return Err("!CompositorBridgeChild::Get()");
|
return Err("!CompositorBridgeChild::Get()");
|
||||||
}
|
}
|
||||||
|
|
||||||
outOfProcess.mWebGLChild = new WebGLChild(*this);
|
// Construct the WebGL command queue, used to send commands from the client
|
||||||
outOfProcess.mWebGLChild = static_cast<dom::WebGLChild*>(
|
// process to the host for execution. It takes a response queue that is
|
||||||
cbc->SendPWebGLConstructor(outOfProcess.mWebGLChild));
|
// used to return responses to synchronous messages.
|
||||||
if (!outOfProcess.mWebGLChild) {
|
// 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,
|
||||||
|
¬Lost.info)) {
|
||||||
return Err("SendPWebGLConstructor failed");
|
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), ¬Lost.info)) {
|
|
||||||
return Err("WebGL actor Initialize failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
notLost.outOfProcess = Some(std::move(outOfProcess));
|
notLost.outOfProcess = Some(std::move(outOfProcess));
|
||||||
return Ok();
|
return Ok();
|
||||||
}();
|
}();
|
||||||
|
@ -972,16 +941,8 @@ already_AddRefed<gfx::SourceSurface> ClientWebGLContext::GetSurfaceSnapshot(
|
||||||
|
|
||||||
const auto range = Range<uint8_t>(map.GetData(), stride * size.y);
|
const auto range = Range<uint8_t>(map.GetData(), stride * size.y);
|
||||||
auto view = RawBufferView(range);
|
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) {
|
const auto swapRowRedBlue = [&](uint8_t* const row) {
|
||||||
|
@ -1623,18 +1584,8 @@ void ClientWebGLContext::GetInternalformatParameter(
|
||||||
JSContext* cx, GLenum target, GLenum internalformat, GLenum pname,
|
JSContext* cx, GLenum target, GLenum internalformat, GLenum pname,
|
||||||
JS::MutableHandle<JS::Value> retval, ErrorResult& rv) {
|
JS::MutableHandle<JS::Value> retval, ErrorResult& rv) {
|
||||||
retval.set(JS::NullValue());
|
retval.set(JS::NullValue());
|
||||||
const auto notLost =
|
auto maybe =
|
||||||
mNotLost; // Hold a strong-ref to prevent LoseContext=>UAF.
|
Run<RPROC(GetInternalformatParameter)>(target, internalformat, pname);
|
||||||
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");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!maybe) {
|
if (!maybe) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2835,15 +2786,7 @@ void ClientWebGLContext::GetBufferSubData(GLenum target, GLintptr srcByteOffset,
|
||||||
}
|
}
|
||||||
auto view = RawBuffer<uint8_t>(byteLen, bytes);
|
auto view = RawBuffer<uint8_t>(byteLen, bytes);
|
||||||
|
|
||||||
const auto notLost =
|
Run<RPROC(GetBufferSubData)>(target, srcByteOffset, view);
|
||||||
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");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////
|
////
|
||||||
|
@ -3591,18 +3534,10 @@ void ClientWebGLContext::TexImage(uint8_t funcDims, GLenum imageTarget,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto notLost =
|
// TODO: Convert TexImageSource into something IPC-capable.
|
||||||
mNotLost; // Hold a strong-ref to prevent LoseContext=>UAF.
|
Run<RPROC(TexImage)>(imageTarget, static_cast<uint32_t>(level), respecFormat,
|
||||||
if (!notLost) return;
|
CastUvec3(offset), CastUvec3(size), pi, src,
|
||||||
const auto& inProcessContext = notLost->inProcess;
|
*GetCanvas());
|
||||||
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");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientWebGLContext::CompressedTexImage(bool sub, uint8_t funcDims,
|
void ClientWebGLContext::CompressedTexImage(bool sub, uint8_t funcDims,
|
||||||
|
@ -4088,16 +4023,7 @@ void ClientWebGLContext::ReadPixels(GLint x, GLint y, GLsizei width,
|
||||||
state.mPixelPackState};
|
state.mPixelPackState};
|
||||||
const auto range = Range<uint8_t>(bytes, byteLen);
|
const auto range = Range<uint8_t>(bytes, byteLen);
|
||||||
auto view = RawBufferView(range);
|
auto view = RawBufferView(range);
|
||||||
|
Run<RPROC(ReadPixels)>(desc, view);
|
||||||
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");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ClientWebGLContext::ReadPixels_SharedPrecheck(
|
bool ClientWebGLContext::ReadPixels_SharedPrecheck(
|
||||||
|
@ -5385,15 +5311,7 @@ const webgl::CompileResult& ClientWebGLContext::GetCompileResult(
|
||||||
const webgl::LinkResult& ClientWebGLContext::GetLinkResult(
|
const webgl::LinkResult& ClientWebGLContext::GetLinkResult(
|
||||||
const WebGLProgramJS& prog) const {
|
const WebGLProgramJS& prog) const {
|
||||||
if (prog.mResult->pending) {
|
if (prog.mResult->pending) {
|
||||||
const auto notLost =
|
*(prog.mResult) = Run<RPROC(GetLinkResult)>(prog.mId);
|
||||||
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.mUniformBlockBindings.resize(
|
prog.mUniformBlockBindings.resize(
|
||||||
prog.mResult->active.activeUniformBlocks.size());
|
prog.mResult->active.activeUniformBlocks.size());
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
|
|
||||||
#include "mozilla/Logging.h"
|
#include "mozilla/Logging.h"
|
||||||
#include "WebGLCrossProcessCommandQueue.h"
|
#include "WebGLCrossProcessCommandQueue.h"
|
||||||
#include "WebGLCommandQueue.h"
|
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
@ -198,8 +197,7 @@ struct RemotingData final {
|
||||||
//
|
//
|
||||||
// where 'A -> B' means "A owns B"
|
// where 'A -> B' means "A owns B"
|
||||||
RefPtr<mozilla::dom::WebGLChild> mWebGLChild;
|
RefPtr<mozilla::dom::WebGLChild> mWebGLChild;
|
||||||
UniquePtr<ClientWebGLCommandSourceP> mCommandSourcePcq;
|
UniquePtr<ClientWebGLCommandSource> mCommandSource;
|
||||||
UniquePtr<ClientWebGLCommandSourceI> mCommandSourceIpdl;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NotLostData final {
|
struct NotLostData final {
|
||||||
|
@ -2083,9 +2081,9 @@ class ClientWebGLContext final : public nsICanvasRenderingContextInternal,
|
||||||
template <size_t command, typename... Args>
|
template <size_t command, typename... Args>
|
||||||
void DispatchAsync(Args&&... aArgs) const {
|
void DispatchAsync(Args&&... aArgs) const {
|
||||||
const auto& oop = *mNotLost->outOfProcess;
|
const auto& oop = *mNotLost->outOfProcess;
|
||||||
QueueStatus status = oop.mCommandSource->RunAsyncCommand(command,
|
PcqStatus status = oop.mCommandSource->RunAsyncCommand(command, aArgs...);
|
||||||
aArgs...);
|
if (!IsSuccess(status)) {
|
||||||
if (!IsSuccess(status)) { if (status == QueueStatus::kOOMError) {
|
if (status == PcqStatus::PcqOOMError) {
|
||||||
JsWarning("Ran out-of-memory during WebGL IPC.");
|
JsWarning("Ran out-of-memory during WebGL IPC.");
|
||||||
}
|
}
|
||||||
// Not much to do but shut down. Since this was a Pcq failure and
|
// 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 {
|
ReturnType DispatchSync(Args&&... aArgs) const {
|
||||||
const auto& oop = *mNotLost->outOfProcess;
|
const auto& oop = *mNotLost->outOfProcess;
|
||||||
ReturnType returnValue;
|
ReturnType returnValue;
|
||||||
QueueStatus status =
|
PcqStatus status =
|
||||||
oop.mCommandSource->RunSyncCommand(command, returnValue, aArgs...);
|
oop.mCommandSource->RunSyncCommand(command, returnValue, aArgs...);
|
||||||
|
|
||||||
if (!IsSuccess(status)) {
|
if (!IsSuccess(status)) {
|
||||||
if (status == QueueStatus::kOOMError) {
|
if (status == PcqStatus::PcqOOMError) {
|
||||||
JsWarning("Ran out-of-memory during WebGL IPC.");
|
JsWarning("Ran out-of-memory during WebGL IPC.");
|
||||||
}
|
}
|
||||||
// Not much to do but shut down. Since this was a Pcq failure and
|
// 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 =
|
const auto status =
|
||||||
oop.mCommandSource->RunVoidSyncCommand(command, aArgs...);
|
oop.mCommandSource->RunVoidSyncCommand(command, aArgs...);
|
||||||
if (!IsSuccess(status)) {
|
if (!IsSuccess(status)) {
|
||||||
if (status == QueueStatus::kOOMError) {
|
if (status == PcqStatus::PcqOOMError) {
|
||||||
JsWarning("Ran out-of-memory during WebGL IPC.");
|
JsWarning("Ran out-of-memory during WebGL IPC.");
|
||||||
}
|
}
|
||||||
// Not much to do but shut down. Since this was a Pcq failure and
|
// 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)
|
HostWebGLContext::HostWebGLContext(OwnerData&& ownerData)
|
||||||
: mOwnerData(std::move(ownerData)) {
|
: mOwnerData(std::move(ownerData)) {
|
||||||
if (mOwnerData.outOfProcess) {
|
if (mOwnerData.outOfProcess) {
|
||||||
if (mOwnerData.outOfProcess->mCommandSinkP) {
|
mOwnerData.outOfProcess->mCommandSink->mHostContext = this;
|
||||||
mOwnerData.outOfProcess->mCommandSinkP->mHostContext = this;
|
|
||||||
}
|
|
||||||
if (mOwnerData.outOfProcess->mCommandSinkI) {
|
|
||||||
mOwnerData.outOfProcess->mCommandSinkI->mHostContext = this;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
@ -14,10 +14,6 @@
|
||||||
#include "WebGL2Context.h"
|
#include "WebGL2Context.h"
|
||||||
#include "WebGLFramebuffer.h"
|
#include "WebGLFramebuffer.h"
|
||||||
#include "WebGLTypes.h"
|
#include "WebGLTypes.h"
|
||||||
#include "WebGLCommandQueue.h"
|
|
||||||
#include "WebGLCrossProcessCommandQueue.h"
|
|
||||||
#include "ProducerConsumerQueue.h"
|
|
||||||
#include "IpdlQueue.h"
|
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
@ -32,6 +28,8 @@
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
|
class HostWebGLCommandSink;
|
||||||
|
|
||||||
extern LazyLogModule gWebGLBridgeLog;
|
extern LazyLogModule gWebGLBridgeLog;
|
||||||
|
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
@ -81,8 +79,7 @@ class HostWebGLContext final : public SupportsWeakPtr<HostWebGLContext> {
|
||||||
|
|
||||||
struct RemotingData final {
|
struct RemotingData final {
|
||||||
dom::WebGLParent& mParent;
|
dom::WebGLParent& mParent;
|
||||||
UniquePtr<HostWebGLCommandSinkP> mCommandSinkP;
|
UniquePtr<HostWebGLCommandSink> mCommandSink;
|
||||||
UniquePtr<HostWebGLCommandSinkI> mCommandSinkI;
|
|
||||||
};
|
};
|
||||||
struct OwnerData final {
|
struct OwnerData final {
|
||||||
Maybe<ClientWebGLContext*> inProcess;
|
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::layers::CompositableHandle from "mozilla/layers/LayersTypes.h";
|
||||||
using mozilla::webgl::ContextLossReason from "mozilla/dom/WebGLIpdl.h";
|
using mozilla::webgl::ContextLossReason from "mozilla/dom/WebGLIpdl.h";
|
||||||
using std::string from "ipc/IPCMessageUtils.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 mozilla {
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
@ -31,26 +25,17 @@ sync refcounted protocol PWebGL
|
||||||
manager PCompositorBridge;
|
manager PCompositorBridge;
|
||||||
|
|
||||||
parent:
|
parent:
|
||||||
sync Initialize(InitContextDesc desc, UniquePtr<HostWebGLCommandSinkP> sinkP,
|
|
||||||
UniquePtr<HostWebGLCommandSinkI> sinkI)
|
|
||||||
returns (InitContextResult res);
|
|
||||||
|
|
||||||
async __delete__();
|
async __delete__();
|
||||||
|
|
||||||
// DLP: TODO: Does this need to be sync?
|
// DLP: TODO: Does this need to be sync?
|
||||||
sync UpdateCompositableHandle(PLayerTransaction aLayerTrans,
|
sync UpdateCompositableHandle(PLayerTransaction aLayerTrans,
|
||||||
CompositableHandle aHandle);
|
CompositableHandle aHandle);
|
||||||
|
|
||||||
sync ExchangeIpdlQueueData(IpdlQueueBuffer aMsg) returns (IpdlQueueBuffers aResponse);
|
|
||||||
|
|
||||||
child:
|
child:
|
||||||
async JsWarning(string text);
|
async JsWarning(string text);
|
||||||
|
|
||||||
// Tell client that this queue needs to be shut down
|
// Tell client that this queue needs to be shut down
|
||||||
async OnContextLoss(ContextLossReason aReason);
|
async OnContextLoss(ContextLossReason aReason);
|
||||||
|
|
||||||
both:
|
|
||||||
async TransmitIpdlQueueData(IpdlQueueBuffer aData);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // dom
|
} // dom
|
||||||
|
|
|
@ -9,7 +9,6 @@ namespace mozilla {
|
||||||
namespace webgl {
|
namespace webgl {
|
||||||
|
|
||||||
mozilla::LazyLogModule gPCQLog("pcq");
|
mozilla::LazyLogModule gPCQLog("pcq");
|
||||||
mozilla::LazyLogModule gIpdlQueueLog("ipdlqueue");
|
|
||||||
|
|
||||||
} // namespace webgl
|
} // namespace webgl
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -6,7 +6,6 @@
|
||||||
#include "WebGLChild.h"
|
#include "WebGLChild.h"
|
||||||
|
|
||||||
#include "ClientWebGLContext.h"
|
#include "ClientWebGLContext.h"
|
||||||
#include "WebGLMethodDispatcher.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
@ -27,10 +26,5 @@ mozilla::ipc::IPCResult WebGLChild::RecvOnContextLoss(
|
||||||
return IPC_OK();
|
return IPC_OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */
|
|
||||||
bool WebGLChild::ShouldSendSync(size_t aCmd, ...) {
|
|
||||||
return WebGLMethodDispatcher::SyncType(aCmd) == CommandSyncType::SYNC;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "mozilla/dom/PWebGLChild.h"
|
#include "mozilla/dom/PWebGLChild.h"
|
||||||
#include "mozilla/dom/IpdlQueue.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
|
@ -17,24 +16,15 @@ class ClientWebGLContext;
|
||||||
|
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
|
||||||
class WebGLChild final : public PWebGLChild,
|
class WebGLChild final : public PWebGLChild {
|
||||||
public SyncProducerActor<WebGLChild>,
|
|
||||||
public AsyncConsumerActor<WebGLChild>,
|
|
||||||
public SupportsWeakPtr<WebGLChild> {
|
|
||||||
public:
|
public:
|
||||||
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(WebGLChild)
|
|
||||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebGLChild, override);
|
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebGLChild, override);
|
||||||
using OtherSideActor = WebGLParent;
|
|
||||||
|
|
||||||
ClientWebGLContext& mContext;
|
ClientWebGLContext& mContext;
|
||||||
|
|
||||||
explicit WebGLChild(ClientWebGLContext&);
|
explicit WebGLChild(ClientWebGLContext&);
|
||||||
|
|
||||||
// For SyncProducerActor:
|
|
||||||
static bool ShouldSendSync(size_t aCmd, ...);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend PWebGLChild;
|
|
||||||
virtual ~WebGLChild();
|
virtual ~WebGLChild();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -21,12 +21,50 @@
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
using mozilla::ipc::IPDLParamTraits;
|
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 };
|
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
|
* A CommandSource is obtained from a CommandQueue. Use it by inserting a
|
||||||
* command (represented by type Command) using InsertCommand, which also
|
* 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 the CommandSink, which must understand the Command+Args combination
|
||||||
* to execute it.
|
* to execute it.
|
||||||
*/
|
*/
|
||||||
template <typename Command, typename _Source>
|
template <typename Command>
|
||||||
class CommandSource {
|
class CommandSource : public BasicSource {
|
||||||
using Source = _Source;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit CommandSource(UniquePtr<Source>&& aSource)
|
explicit CommandSource(UniquePtr<Producer>&& aProducer)
|
||||||
: mSource(std::move(aSource)) {
|
: BasicSource(std::move(aProducer)) {}
|
||||||
MOZ_ASSERT(mSource);
|
|
||||||
|
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>
|
template <typename... Args>
|
||||||
QueueStatus InsertCommand(Command aCommand, Args&&... aArgs) {
|
PcqStatus RunCommand(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) {
|
|
||||||
return InsertCommand(aCommand, std::forward<Args>(aArgs)...);
|
return InsertCommand(aCommand, std::forward<Args>(aArgs)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
// For IPDL:
|
// For IPDL:
|
||||||
CommandSource() = default;
|
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
|
* easily run functions and methods using arguments taken from the command
|
||||||
* queue by calling the Dispatch methods in this class.
|
* queue by calling the Dispatch methods in this class.
|
||||||
*/
|
*/
|
||||||
template <typename Command, typename _Sink>
|
template <typename Command>
|
||||||
class CommandSink {
|
class CommandSink : public BasicSink {
|
||||||
using Sink = _Sink;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit CommandSink(UniquePtr<Sink>&& aSink) : mSink(std::move(aSink)) {
|
explicit CommandSink(UniquePtr<Consumer>&& aConsumer)
|
||||||
MOZ_ASSERT(mSink);
|
: BasicSink(std::move(aConsumer)) {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempts to process the next command in the queue, if one is available.
|
* Attempts to process the next command in the queue, if one is available.
|
||||||
*/
|
*/
|
||||||
CommandResult ProcessOne(const Maybe<TimeDuration>& aTimeout) {
|
CommandResult ProcessOne(const Maybe<TimeDuration>& aTimeout) {
|
||||||
Command command;
|
Command command;
|
||||||
QueueStatus status = (aTimeout.isNothing() || aTimeout.value())
|
PcqStatus status = (aTimeout.isNothing() || aTimeout.value())
|
||||||
? this->mSink->TryWaitRemove(aTimeout, command)
|
? this->mConsumer->TryWaitRemove(aTimeout, command)
|
||||||
: this->mSink->TryRemove(command);
|
: this->mConsumer->TryRemove(command);
|
||||||
|
|
||||||
if (status == QueueStatus::kSuccess) {
|
if (status == PcqStatus::Success) {
|
||||||
if (DispatchCommand(command)) {
|
if (DispatchCommand(command)) {
|
||||||
return CommandResult::kSuccess;
|
return CommandResult::Success;
|
||||||
}
|
}
|
||||||
return CommandResult::kError;
|
return CommandResult::Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status == QueueStatus::kNotReady) {
|
if (status == PcqStatus::PcqNotReady) {
|
||||||
return CommandResult::kQueueEmpty;
|
return CommandResult::QueueEmpty;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status == QueueStatus::kOOMError) {
|
if (status == PcqStatus::PcqOOMError) {
|
||||||
ReportOOM();
|
ReportOOM();
|
||||||
}
|
}
|
||||||
return CommandResult::kError;
|
return CommandResult::Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandResult ProcessOneNow() { return ProcessOne(Some(TimeDuration(0))); }
|
CommandResult ProcessOneNow() { return ProcessOne(Some(TimeDuration(0))); }
|
||||||
|
@ -125,7 +152,7 @@ class CommandSink {
|
||||||
CommandResult result;
|
CommandResult result;
|
||||||
do {
|
do {
|
||||||
result = ProcessOneNow();
|
result = ProcessOneNow();
|
||||||
} while (result == CommandResult::kSuccess);
|
} while (result == CommandResult::Success);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,8 +169,7 @@ class CommandSink {
|
||||||
do {
|
do {
|
||||||
result = ProcessOne(Some(aDuration - (now - start)));
|
result = ProcessOne(Some(aDuration - (now - start)));
|
||||||
now = TimeStamp::Now();
|
now = TimeStamp::Now();
|
||||||
} while ((result == CommandResult::kSuccess) &&
|
} while ((result == CommandResult::Success) && ((now - start) < aDuration));
|
||||||
((now - start) < aDuration));
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,8 +224,6 @@ class CommandSink {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend struct IPDLParamTraits<mozilla::CommandSink<Command, Sink>>;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementations will usually be something like a big switch statement
|
* Implementations will usually be something like a big switch statement
|
||||||
* that calls one of the Dispatch methods in this class.
|
* that calls one of the Dispatch methods in this class.
|
||||||
|
@ -213,27 +237,26 @@ class CommandSink {
|
||||||
virtual void ReportOOM() {}
|
virtual void ReportOOM() {}
|
||||||
|
|
||||||
template <typename... Args, size_t... Indices>
|
template <typename... Args, size_t... Indices>
|
||||||
QueueStatus CallTryRemove(std::tuple<Args...>& aArgs,
|
PcqStatus CallTryRemove(std::tuple<Args...>& aArgs,
|
||||||
std::index_sequence<Indices...>) {
|
std::index_sequence<Indices...>) {
|
||||||
QueueStatus status = mSink->TryRemove(std::get<Indices>(aArgs)...);
|
PcqStatus status = mConsumer->TryRemove(std::get<Indices>(aArgs)...);
|
||||||
// The CommandQueue inserts the command and the args together as an atomic
|
// The CommandQueue inserts the command and the args together as an atomic
|
||||||
// operation. We already read the command so the args must also be
|
// operation. We already read the command so the args must also be
|
||||||
// available.
|
// available.
|
||||||
MOZ_ASSERT(status != QueueStatus::kNotReady);
|
MOZ_ASSERT(status != PcqStatus::PcqNotReady);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
QueueStatus CallTryRemove(std::tuple<>& aArgs,
|
PcqStatus CallTryRemove(std::tuple<>& aArgs,
|
||||||
std::make_integer_sequence<size_t, 0>) {
|
std::make_integer_sequence<size_t, 0>) {
|
||||||
return QueueStatus::kSuccess;
|
return PcqStatus::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename MethodType, typename... Args,
|
template <typename T, typename MethodType, typename... Args,
|
||||||
size_t... Indices,
|
size_t... Indices, typename ReturnType>
|
||||||
typename ReturnType =
|
std::result_of<MethodType> CallMethod(T& aObj, MethodType aMethod,
|
||||||
typename mozilla::FunctionTypeTraits<MethodType>::ReturnType>
|
std::tuple<Args...>& aArgs,
|
||||||
ReturnType CallMethod(T& aObj, MethodType aMethod, std::tuple<Args...>& aArgs,
|
std::index_sequence<Indices...>) {
|
||||||
std::index_sequence<Indices...>) {
|
|
||||||
return (aObj.*aMethod)(std::forward<Args>(std::get<Indices>(aArgs))...);
|
return (aObj.*aMethod)(std::forward<Args>(std::get<Indices>(aArgs))...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,110 +269,96 @@ class CommandSink {
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
bool ReadArgs(std::tuple<Args...>& aArgs) {
|
bool ReadArgs(std::tuple<Args...>& aArgs) {
|
||||||
QueueStatus status =
|
PcqStatus status = CallTryRemove(aArgs, std::index_sequence_for<Args...>{});
|
||||||
CallTryRemove(aArgs, std::index_sequence_for<Args...>{});
|
|
||||||
return IsSuccess(status);
|
return IsSuccess(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
UniquePtr<Sink> mSink;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum SyncResponse : uint8_t { RESPONSE_NAK, RESPONSE_ACK };
|
enum SyncResponse : uint8_t { RESPONSE_NAK, RESPONSE_ACK };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the Source for a SyncCommandSink. It takes an extra queue,
|
* This is the Source for a SyncCommandSink. It takes an extra PCQ,
|
||||||
* the ResponseQueue, and uses it to receive synchronous responses from
|
* the ResponsePcq, and uses it to receive synchronous responses from
|
||||||
* the sink. The ResponseQueue is a regular queue, not a CommandQueue.
|
* the sink. The ResponsePcq is a regular ProducerConsumerQueue,
|
||||||
|
* not a CommandQueue.
|
||||||
*/
|
*/
|
||||||
template <typename Command, typename _Source, typename _ResponseQueue>
|
template <typename Command>
|
||||||
class SyncCommandSource : public CommandSource<Command, _Source> {
|
class SyncCommandSource : public CommandSource<Command> {
|
||||||
public:
|
public:
|
||||||
using BaseType = CommandSource<Command, _Source>;
|
using BaseType = CommandSource<Command>;
|
||||||
using Source = _Source;
|
SyncCommandSource(UniquePtr<Producer>&& aProducer,
|
||||||
using ResponseQueue = _ResponseQueue;
|
UniquePtr<Consumer>&& aResponseConsumer)
|
||||||
using ResponseSink = typename ResponseQueue::Consumer;
|
: CommandSource<Command>(std::move(aProducer)),
|
||||||
|
mConsumer(std::move(aResponseConsumer)) {}
|
||||||
SyncCommandSource(UniquePtr<Source>&& aSource,
|
|
||||||
UniquePtr<ResponseSink>&& aResponseSink)
|
|
||||||
: CommandSource<Command, Source>(std::move(aSource)),
|
|
||||||
mResponseSink(std::move(aResponseSink)) {}
|
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
QueueStatus RunAsyncCommand(Command aCommand, Args&&... aArgs) {
|
PcqStatus RunAsyncCommand(Command aCommand, Args&&... aArgs) {
|
||||||
return this->RunCommand(aCommand, std::forward<Args>(aArgs)...);
|
return this->RunCommand(aCommand, std::forward<Args>(aArgs)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
QueueStatus RunVoidSyncCommand(Command aCommand, Args&&... aArgs) {
|
PcqStatus RunVoidSyncCommand(Command aCommand, Args&&... aArgs) {
|
||||||
QueueStatus status =
|
PcqStatus status = RunAsyncCommand(aCommand, std::forward<Args>(aArgs)...);
|
||||||
RunAsyncCommand(aCommand, std::forward<Args>(aArgs)...);
|
|
||||||
return IsSuccess(status) ? this->ReadSyncResponse() : status;
|
return IsSuccess(status) ? this->ReadSyncResponse() : status;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ResultType, typename... Args>
|
template <typename ResultType, typename... Args>
|
||||||
QueueStatus RunSyncCommand(Command aCommand, ResultType& aReturn,
|
PcqStatus RunSyncCommand(Command aCommand, ResultType& aReturn,
|
||||||
Args&&... aArgs) {
|
Args&&... aArgs) {
|
||||||
QueueStatus status =
|
PcqStatus status =
|
||||||
RunVoidSyncCommand(aCommand, std::forward<Args>(aArgs)...);
|
RunVoidSyncCommand(aCommand, std::forward<Args>(aArgs)...);
|
||||||
return IsSuccess(status) ? this->ReadResult(aReturn) : status;
|
return IsSuccess(status) ? this->ReadResult(aReturn) : status;
|
||||||
}
|
}
|
||||||
|
|
||||||
// for IPDL:
|
// for IPDL:
|
||||||
SyncCommandSource() = default;
|
SyncCommandSource() = default;
|
||||||
friend struct mozilla::ipc::IPDLParamTraits<
|
friend struct mozilla::ipc::IPDLParamTraits<SyncCommandSource<Command>>;
|
||||||
SyncCommandSource<Command, Source, ResponseQueue>>;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QueueStatus ReadSyncResponse() {
|
PcqStatus ReadSyncResponse() {
|
||||||
SyncResponse response;
|
SyncResponse response;
|
||||||
QueueStatus status =
|
PcqStatus status =
|
||||||
mResponseSink->TryWaitRemove(Nothing() /* wait forever */, response);
|
mConsumer->TryWaitRemove(Nothing() /* wait forever */, response);
|
||||||
MOZ_ASSERT(status != QueueStatus::kNotReady);
|
MOZ_ASSERT(status != PcqStatus::PcqNotReady);
|
||||||
|
|
||||||
if (IsSuccess(status) && response != RESPONSE_ACK) {
|
if (IsSuccess(status) && response != RESPONSE_ACK) {
|
||||||
return QueueStatus::kFatalError;
|
return PcqStatus::PcqFatalError;
|
||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
QueueStatus ReadResult(T& aResult) {
|
PcqStatus ReadResult(T& aResult) {
|
||||||
QueueStatus status = mResponseSink->TryRemove(aResult);
|
PcqStatus status = mConsumer->TryRemove(aResult);
|
||||||
// The Sink posts the response code and result as an atomic transaction. We
|
// The Sink posts the response code and result as an atomic transaction. We
|
||||||
// already read the response code so the result must be available.
|
// already read the response code so the result must be available.
|
||||||
MOZ_ASSERT(status != QueueStatus::kNotReady);
|
MOZ_ASSERT(status != PcqStatus::PcqNotReady);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
UniquePtr<ResponseSink> mResponseSink;
|
UniquePtr<Consumer> mConsumer;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the Sink for a SyncCommandSource. It takes an extra queue, the
|
* This is the Sink for a SyncCommandSource. It takes an extra PCQ, the
|
||||||
* ResponseQueue, and uses it to issue synchronous responses to the client.
|
* ResponsePcq, and uses it to issue synchronous responses to the client.
|
||||||
* Subclasses can use the DispatchSync methods in this class in their
|
* Subclasses can use the DispatchSync methods in this class in their
|
||||||
* DispatchCommand implementations.
|
* DispatchCommand implementations.
|
||||||
* The ResponseQueue is not a CommandQueue.
|
* The ResponsePcq is not a CommandQueue.
|
||||||
*/
|
*/
|
||||||
template <typename Command, typename _Sink, typename _ResponseQueue>
|
template <typename Command>
|
||||||
class SyncCommandSink : public CommandSink<Command, _Sink> {
|
class SyncCommandSink : public CommandSink<Command> {
|
||||||
using BaseType = CommandSink<Command, _Sink>;
|
using BaseType = CommandSink<Command>;
|
||||||
using ResponseQueue = _ResponseQueue;
|
|
||||||
using Sink = _Sink;
|
|
||||||
using ResponseSource = typename ResponseQueue::Producer;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SyncCommandSink(UniquePtr<Sink>&& aSink,
|
SyncCommandSink(UniquePtr<Consumer>&& aConsumer,
|
||||||
UniquePtr<ResponseSource>&& aResponseSource)
|
UniquePtr<Producer>&& aResponseProducer)
|
||||||
: CommandSink<Command, Sink>(std::move(aSink)),
|
: CommandSink<Command>(std::move(aConsumer)),
|
||||||
mResponseSource(std::move(aResponseSource)) {
|
mProducer(std::move(aResponseProducer)) {}
|
||||||
MOZ_ASSERT(mResponseSource);
|
|
||||||
}
|
|
||||||
|
|
||||||
// for IPDL:
|
// for IPDL:
|
||||||
SyncCommandSink() = default;
|
SyncCommandSink() = default;
|
||||||
friend struct mozilla::ipc::IPDLParamTraits<
|
friend struct mozilla::ipc::IPDLParamTraits<SyncCommandSink<Command>>;
|
||||||
SyncCommandSink<Command, Sink, ResponseQueue>>;
|
|
||||||
|
|
||||||
// Places RESPONSE_ACK and the typed return value, or RESPONSE_NAK, in
|
// Places RESPONSE_ACK and the typed return value, or RESPONSE_NAK, in
|
||||||
// the response queue,
|
// the response queue,
|
||||||
|
@ -482,7 +491,7 @@ class SyncCommandSink : public CommandSink<Command, _Sink> {
|
||||||
protected:
|
protected:
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
bool WriteArgs(const Args&... aArgs) {
|
bool WriteArgs(const Args&... aArgs) {
|
||||||
return IsSuccess(mResponseSource->TryInsert(aArgs...));
|
return IsSuccess(mProducer->TryInsert(aArgs...));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
|
@ -496,7 +505,25 @@ class SyncCommandSink : public CommandSink<Command, _Sink> {
|
||||||
return WriteArgs(nak);
|
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.
|
* use to dispatch sync/async commands to a method via a CommandSink.
|
||||||
* See DECLARE_METHOD_DISPATCHER and DEFINE_METHOD_DISPATCHER.
|
* See DECLARE_METHOD_DISPATCHER and DEFINE_METHOD_DISPATCHER.
|
||||||
*/
|
*/
|
||||||
template <typename Derived>
|
template <typename Derived, typename _SinkType>
|
||||||
struct MethodDispatcher {
|
struct MethodDispatcher {
|
||||||
|
using SinkType = _SinkType;
|
||||||
template <CommandSyncType syncType>
|
template <CommandSyncType syncType>
|
||||||
struct DispatchMethod;
|
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
|
// Specialization for dispatching synchronous methods
|
||||||
template <>
|
template <>
|
||||||
struct DispatchMethod<CommandSyncType::ASYNC> {
|
struct DispatchMethod<CommandSyncType::SYNC> {
|
||||||
template <typename MethodType, typename ObjectType, typename SinkType>
|
template <typename MethodType, typename ObjectType>
|
||||||
static MOZ_ALWAYS_INLINE bool Run(SinkType& aSink, MethodType mMethod,
|
static MOZ_ALWAYS_INLINE bool Run(SinkType& aSink, MethodType aMethod,
|
||||||
ObjectType& aObj) {
|
ObjectType& aObj) {
|
||||||
return aSink.DispatchAsyncMethod(aObj, mMethod);
|
return aSink.DispatchSyncMethod(aObj, aMethod);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
*/
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Declares a MethodDispatcher with the given name and CommandSink type.
|
// Declares a MethodDispatcher with the given name and CommandSink type.
|
||||||
// The ObjectType is the type of the object this class will dispatch methods to.
|
// The ObjectType is the type of the object this class will dispatch methods to.
|
||||||
#define DECLARE_METHOD_DISPATCHER(_DISPATCHER, _OBJECTTYPE) \
|
#define DECLARE_METHOD_DISPATCHER(_DISPATCHER, _SINKTYPE, _OBJECTTYPE) \
|
||||||
struct _DISPATCHER : public MethodDispatcher<_DISPATCHER> { \
|
struct _DISPATCHER : public MethodDispatcher<_DISPATCHER, _SINKTYPE> { \
|
||||||
using ObjectType = _OBJECTTYPE; \
|
using ObjectType = _OBJECTTYPE; \
|
||||||
template <size_t commandId> \
|
template <size_t commandId = 0> \
|
||||||
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> \
|
|
||||||
static MOZ_ALWAYS_INLINE bool DispatchCommand(size_t aId, SinkType& aSink, \
|
static MOZ_ALWAYS_INLINE bool DispatchCommand(size_t aId, SinkType& aSink, \
|
||||||
ObjectType& aObj) { \
|
ObjectType& aObj) { \
|
||||||
return IdDispatcher<commandId>::DispatchCommand(aId, aSink, aObj); \
|
MOZ_ASSERT_UNREACHABLE("Unhandled command ID"); \
|
||||||
} \
|
return false; \
|
||||||
template <size_t commandId = 0> \
|
|
||||||
static MOZ_ALWAYS_INLINE CommandSyncType SyncType(size_t aId) { \
|
|
||||||
return IdDispatcher<commandId>::SyncType(aId); \
|
|
||||||
} \
|
} \
|
||||||
template <size_t commandId> \
|
template <size_t commandId> \
|
||||||
|
static MOZ_ALWAYS_INLINE bool Dispatch(SinkType& aSink, ObjectType& aObj); \
|
||||||
|
template <size_t commandId> \
|
||||||
struct MethodInfo; \
|
struct MethodInfo; \
|
||||||
template <size_t commandId> \
|
template <size_t commandId> \
|
||||||
static constexpr CommandSyncType SyncType(); \
|
static constexpr CommandSyncType SyncType(); \
|
||||||
|
@ -570,111 +584,127 @@ struct MethodDispatcher {
|
||||||
// id. The handler uses a CommandSink to read parameters, call the
|
// id. The handler uses a CommandSink to read parameters, call the
|
||||||
// given method using the given synchronization protocol, and provide
|
// given method using the given synchronization protocol, and provide
|
||||||
// compile-time lookup of the ID by class method.
|
// compile-time lookup of the ID by class method.
|
||||||
#define DEFINE_METHOD_DISPATCHER(_DISPATCHER, _ID, _METHOD, _SYNC) \
|
#define DEFINE_METHOD_DISPATCHER(_DISPATCHER, _ID, _METHOD, _SYNC) \
|
||||||
template <> \
|
/* template <> \
|
||||||
struct _DISPATCHER::MethodInfo<_ID> { \
|
bool _DISPATCHER::DispatchCommand<_ID>(size_t aId, SinkType & aSink, \
|
||||||
using MethodType = decltype(&_METHOD); \
|
ObjectType & aObj) { \
|
||||||
}; \
|
return CommandDispatchDriver<_DISPATCHER>::DispatchCommandHelper<_ID>( \
|
||||||
template <> \
|
aId, aSink, aObj); \
|
||||||
constexpr CommandSyncType _DISPATCHER::SyncType<_ID>() { \
|
} \
|
||||||
return _SYNC; \
|
template <> \
|
||||||
} \
|
bool _DISPATCHER::Dispatch<_ID>(SinkType & aSink, ObjectType & aObj) { \
|
||||||
template <> \
|
return DispatchMethod<_SYNC>::Run(aSink, &_METHOD, aObj); \
|
||||||
constexpr size_t _DISPATCHER::Id<decltype(&_METHOD), &_METHOD>() { \
|
} */ \
|
||||||
return _ID; \
|
template <> \
|
||||||
} \
|
struct _DISPATCHER::MethodInfo<_ID> { \
|
||||||
template <> \
|
using MethodType = decltype(&_METHOD); \
|
||||||
struct _DISPATCHER::IdDispatcher<_ID> { \
|
}; \
|
||||||
template <typename SinkType> \
|
template <> \
|
||||||
static MOZ_ALWAYS_INLINE bool DispatchCommand(size_t aId, SinkType& aSink, \
|
constexpr CommandSyncType _DISPATCHER::SyncType<_ID>() { \
|
||||||
ObjectType& aObj) { \
|
return _SYNC; \
|
||||||
return (_ID == aId) ? DispatchMethod<_SYNC>::Run(aSink, &_METHOD, aObj) \
|
} \
|
||||||
: _DISPATCHER::DispatchCommand<SinkType, _ID + 1>( \
|
template <> \
|
||||||
aId, aSink, aObj); \
|
constexpr size_t _DISPATCHER::Id<decltype(&_METHOD), &_METHOD>() { \
|
||||||
} \
|
return _ID; \
|
||||||
static MOZ_ALWAYS_INLINE CommandSyncType SyncType(size_t aId) { \
|
}
|
||||||
return (_ID == aId) ? _DISPATCHER::SyncType<_ID>() \
|
|
||||||
: _DISPATCHER::SyncType<_ID + 1>(aId); \
|
|
||||||
} \
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace ipc {
|
namespace ipc {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct IPDLParamTraits;
|
struct IPDLParamTraits;
|
||||||
|
|
||||||
template <typename Command, typename Source>
|
template <>
|
||||||
struct IPDLParamTraits<mozilla::CommandSource<Command, Source>> {
|
struct IPDLParamTraits<mozilla::BasicSource> {
|
||||||
public:
|
public:
|
||||||
typedef mozilla::CommandSource<Command, Source> paramType;
|
typedef mozilla::BasicSource paramType;
|
||||||
|
|
||||||
static void Write(IPC::Message* aMsg, IProtocol* aActor,
|
static void Write(IPC::Message* aMsg, IProtocol* aActor,
|
||||||
const paramType& aParam) {
|
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,
|
static bool Read(const IPC::Message* aMsg, PickleIterator* aIter,
|
||||||
IProtocol* aActor, paramType* aResult) {
|
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>
|
template <>
|
||||||
struct IPDLParamTraits<mozilla::CommandSink<Command, Sink>> {
|
struct IPDLParamTraits<mozilla::BasicSink> {
|
||||||
public:
|
public:
|
||||||
typedef mozilla::CommandSink<Command, Sink> paramType;
|
typedef mozilla::BasicSink paramType;
|
||||||
|
|
||||||
static void Write(IPC::Message* aMsg, IProtocol* aActor,
|
static void Write(IPC::Message* aMsg, IProtocol* aActor,
|
||||||
const paramType& aParam) {
|
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,
|
static bool Read(const IPC::Message* aMsg, PickleIterator* aIter,
|
||||||
IProtocol* aActor, paramType* aResult) {
|
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>
|
template <typename Command>
|
||||||
struct IPDLParamTraits<
|
struct IPDLParamTraits<mozilla::CommandSource<Command>>
|
||||||
mozilla::SyncCommandSource<Command, Source, ResponseQueue>>
|
: public IPDLParamTraits<mozilla::BasicSource> {
|
||||||
: public IPDLParamTraits<mozilla::CommandSource<Command, Source>> {
|
|
||||||
public:
|
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;
|
typedef typename paramType::BaseType paramBaseType;
|
||||||
|
|
||||||
static void Write(IPC::Message* aMsg, IProtocol* aActor,
|
static void Write(IPC::Message* aMsg, IProtocol* aActor,
|
||||||
const paramType& aParam) {
|
const paramType& aParam) {
|
||||||
WriteIPDLParam(aMsg, aActor, static_cast<const paramBaseType&>(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,
|
static bool Read(const IPC::Message* aMsg, PickleIterator* aIter,
|
||||||
IProtocol* aActor, paramType* aParam) {
|
IProtocol* aActor, paramType* aParam) {
|
||||||
bool result =
|
bool result =
|
||||||
ReadIPDLParam(aMsg, aIter, aActor, static_cast<paramBaseType*>(aParam));
|
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>
|
template <typename Command>
|
||||||
struct IPDLParamTraits<mozilla::SyncCommandSink<Command, Sink, ResponseQueue>>
|
struct IPDLParamTraits<mozilla::SyncCommandSink<Command>>
|
||||||
: public IPDLParamTraits<mozilla::CommandSink<Command, Sink>> {
|
: public IPDLParamTraits<mozilla::CommandSink<Command>> {
|
||||||
public:
|
public:
|
||||||
typedef mozilla::SyncCommandSink<Command, Sink, ResponseQueue> paramType;
|
typedef mozilla::SyncCommandSink<Command> paramType;
|
||||||
typedef typename paramType::BaseType paramBaseType;
|
typedef typename paramType::BaseType paramBaseType;
|
||||||
|
|
||||||
static void Write(IPC::Message* aMsg, IProtocol* aActor,
|
static void Write(IPC::Message* aMsg, IProtocol* aActor,
|
||||||
const paramType& aParam) {
|
const paramType& aParam) {
|
||||||
WriteIPDLParam(aMsg, aActor, static_cast<const paramBaseType&>(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,
|
static bool Read(const IPC::Message* aMsg, PickleIterator* aIter,
|
||||||
IProtocol* aActor, paramType* aParam) {
|
IProtocol* aActor, paramType* aParam) {
|
||||||
bool result =
|
bool result =
|
||||||
ReadIPDLParam(aMsg, aIter, aActor, static_cast<paramBaseType*>(aParam));
|
ReadIPDLParam(aMsg, aIter, aActor, static_cast<paramBaseType*>(aParam));
|
||||||
return result &&
|
return result && ReadIPDLParam(aMsg, aIter, aActor, &aParam->mProducer);
|
||||||
ReadIPDLParam(aMsg, aIter, aActor, &aParam->mResponseSource);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -8,14 +8,12 @@
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
#if 0
|
bool HostWebGLCommandSink::DispatchCommand(size_t command) {
|
||||||
bool HostWebGLCommandSink<Consumer, Queue>::DispatchCommand(size_t command) {
|
|
||||||
if (!mHostContext) {
|
if (!mHostContext) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return WebGLMethodDispatcher::DispatchCommand(command, *this, *mHostContext);
|
return WebGLMethodDispatcher::DispatchCommand(command, *this, *mHostContext);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
@ -7,16 +7,9 @@
|
||||||
#define WEBGLCROSSPROCESSCOMMANDQUEUE_H_
|
#define WEBGLCROSSPROCESSCOMMANDQUEUE_H_
|
||||||
|
|
||||||
#include "mozilla/dom/WebGLCommandQueue.h"
|
#include "mozilla/dom/WebGLCommandQueue.h"
|
||||||
#include "ProducerConsumerQueue.h"
|
|
||||||
#include "IpdlQueue.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
namespace dom {
|
|
||||||
class WebGLParent;
|
|
||||||
class WebGLChild;
|
|
||||||
} // namespace dom
|
|
||||||
|
|
||||||
namespace layers {
|
namespace layers {
|
||||||
class PCompositorBridgeParent;
|
class PCompositorBridgeParent;
|
||||||
}
|
}
|
||||||
|
@ -28,9 +21,7 @@ using mozilla::webgl::ProducerConsumerQueue;
|
||||||
/**
|
/**
|
||||||
* The source for the WebGL Command Queue.
|
* The source for the WebGL Command Queue.
|
||||||
*/
|
*/
|
||||||
using ClientWebGLCommandSourceP =
|
using ClientWebGLCommandSource = SyncCommandSource<size_t>;
|
||||||
SyncCommandSource<size_t, mozilla::webgl::PcqProducer,
|
|
||||||
mozilla::webgl::ProducerConsumerQueue>;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The sink for the WebGL Command Queue. This object is created in the client
|
* 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
|
* then uses for executing methods. Add new commands to DispatchCommand using
|
||||||
* the WEBGL_SYNC_COMMAND and WEBGL_ASYNC_COMMAND macros.
|
* the WEBGL_SYNC_COMMAND and WEBGL_ASYNC_COMMAND macros.
|
||||||
*/
|
*/
|
||||||
template <typename Consumer, typename Queue>
|
class HostWebGLCommandSink : public SyncCommandSink<size_t> {
|
||||||
class HostWebGLCommandSink final
|
|
||||||
: public SyncCommandSink<size_t, Consumer, Queue> {
|
|
||||||
public:
|
public:
|
||||||
HostWebGLCommandSink(UniquePtr<Consumer>&& aConsumer,
|
HostWebGLCommandSink(UniquePtr<Consumer>&& aConsumer,
|
||||||
UniquePtr<typename Queue::Producer>&& aResponseProducer)
|
UniquePtr<Producer>&& aResponseProducer)
|
||||||
: SyncCommandSink<size_t, Consumer, Queue>(
|
: SyncCommandSink(std::move(aConsumer), std::move(aResponseProducer)) {}
|
||||||
std::move(aConsumer), std::move(aResponseProducer)) {}
|
|
||||||
|
|
||||||
HostWebGLContext* mHostContext = nullptr;
|
HostWebGLContext* mHostContext = nullptr;
|
||||||
|
|
||||||
// For IPDL:
|
|
||||||
HostWebGLCommandSink() = default;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
// For IPDL:
|
||||||
friend struct mozilla::ipc::IPDLParamTraits<HostWebGLCommandSink>;
|
friend struct mozilla::ipc::IPDLParamTraits<HostWebGLCommandSink>;
|
||||||
friend class mozilla::layers::PCompositorBridgeParent;
|
friend class mozilla::layers::PCompositorBridgeParent;
|
||||||
|
HostWebGLCommandSink() = default;
|
||||||
|
|
||||||
bool DispatchCommand(size_t command) override {
|
bool DispatchCommand(size_t command) override;
|
||||||
MOZ_CRASH("TODO:");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
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 {
|
namespace ipc {
|
||||||
|
|
||||||
template <typename Consumer, typename Queue>
|
template <>
|
||||||
struct IPDLParamTraits<mozilla::HostWebGLCommandSink<Consumer, Queue>>
|
struct IPDLParamTraits<mozilla::HostWebGLCommandSink>
|
||||||
: public IPDLParamTraits<
|
: public IPDLParamTraits<mozilla::SyncCommandSink<size_t>> {
|
||||||
mozilla::SyncCommandSink<size_t, Consumer, Queue>> {
|
|
||||||
public:
|
public:
|
||||||
typedef mozilla::HostWebGLCommandSink<Consumer, Queue> paramType;
|
typedef mozilla::HostWebGLCommandSink paramType;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ipc
|
} // namespace ipc
|
||||||
|
|
|
@ -9,13 +9,14 @@
|
||||||
#include "TexUnpackBlob.h"
|
#include "TexUnpackBlob.h"
|
||||||
#include "WebGLCrossProcessCommandQueue.h"
|
#include "WebGLCrossProcessCommandQueue.h"
|
||||||
#include "HostWebGLContext.h"
|
#include "HostWebGLContext.h"
|
||||||
#include "WebGLQueueParamTraits.h"
|
#include "WebGLPcqParamTraits.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
// The WebGLMethodDispatcher will dispatch commands read from the
|
// The WebGLMethodDispatcher will dispatch commands read from the
|
||||||
// HostWebGLCommandSink and issue them to a given HostWebGLContext.
|
// 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
|
// Defines each method the WebGLMethodDispatcher handles. The COUNTER value
|
||||||
// is used as a cross-process ID for each of the methods.
|
// 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::DeleteVertexArray)
|
||||||
|
|
||||||
DEFINE_ASYNC(HostWebGLContext::ClearVRFrame)
|
DEFINE_ASYNC(HostWebGLContext::ClearVRFrame)
|
||||||
// DEFINE_SYNC(HostWebGLContext::GetVRFrame)
|
DEFINE_SYNC(HostWebGLContext::GetVRFrame)
|
||||||
|
|
||||||
DEFINE_ASYNC(HostWebGLContext::Disable)
|
DEFINE_ASYNC(HostWebGLContext::Disable)
|
||||||
DEFINE_ASYNC(HostWebGLContext::Enable)
|
DEFINE_ASYNC(HostWebGLContext::Enable)
|
||||||
DEFINE_ASYNC(HostWebGLContext::GenerateError)
|
DEFINE_ASYNC(HostWebGLContext::GenerateError)
|
||||||
DEFINE_SYNC(HostWebGLContext::GetCompileResult)
|
DEFINE_SYNC(HostWebGLContext::GetCompileResult)
|
||||||
DEFINE_SYNC(HostWebGLContext::GetFragDataLocation)
|
DEFINE_SYNC(HostWebGLContext::GetFragDataLocation)
|
||||||
// DEFINE_SYNC(HostWebGLContext::GetLinkResult)
|
DEFINE_SYNC(HostWebGLContext::GetLinkResult)
|
||||||
DEFINE_SYNC(HostWebGLContext::InitializeCanvasRenderer)
|
DEFINE_SYNC(HostWebGLContext::InitializeCanvasRenderer)
|
||||||
DEFINE_SYNC(HostWebGLContext::IsEnabled)
|
DEFINE_SYNC(HostWebGLContext::IsEnabled)
|
||||||
DEFINE_ASYNC(HostWebGLContext::Resize)
|
DEFINE_ASYNC(HostWebGLContext::Resize)
|
||||||
|
@ -113,21 +114,21 @@ DEFINE_ASYNC(HostWebGLContext::Viewport)
|
||||||
DEFINE_ASYNC(HostWebGLContext::BindBuffer)
|
DEFINE_ASYNC(HostWebGLContext::BindBuffer)
|
||||||
DEFINE_ASYNC(HostWebGLContext::BindBufferRange)
|
DEFINE_ASYNC(HostWebGLContext::BindBufferRange)
|
||||||
DEFINE_ASYNC(HostWebGLContext::CopyBufferSubData)
|
DEFINE_ASYNC(HostWebGLContext::CopyBufferSubData)
|
||||||
// DEFINE_ASYNC(HostWebGLContext::GetBufferSubData)
|
DEFINE_ASYNC(HostWebGLContext::GetBufferSubData)
|
||||||
DEFINE_ASYNC(HostWebGLContext::BufferData)
|
DEFINE_ASYNC(HostWebGLContext::BufferData)
|
||||||
DEFINE_ASYNC(HostWebGLContext::BufferSubData)
|
DEFINE_ASYNC(HostWebGLContext::BufferSubData)
|
||||||
DEFINE_ASYNC(HostWebGLContext::BlitFramebuffer)
|
DEFINE_ASYNC(HostWebGLContext::BlitFramebuffer)
|
||||||
DEFINE_ASYNC(HostWebGLContext::InvalidateFramebuffer)
|
DEFINE_ASYNC(HostWebGLContext::InvalidateFramebuffer)
|
||||||
DEFINE_ASYNC(HostWebGLContext::InvalidateSubFramebuffer)
|
DEFINE_ASYNC(HostWebGLContext::InvalidateSubFramebuffer)
|
||||||
DEFINE_ASYNC(HostWebGLContext::ReadBuffer)
|
DEFINE_ASYNC(HostWebGLContext::ReadBuffer)
|
||||||
// DEFINE_SYNC(HostWebGLContext::GetInternalformatParameter)
|
DEFINE_SYNC(HostWebGLContext::GetInternalformatParameter)
|
||||||
DEFINE_ASYNC(HostWebGLContext::RenderbufferStorageMultisample)
|
DEFINE_ASYNC(HostWebGLContext::RenderbufferStorageMultisample)
|
||||||
DEFINE_ASYNC(HostWebGLContext::ActiveTexture)
|
DEFINE_ASYNC(HostWebGLContext::ActiveTexture)
|
||||||
DEFINE_ASYNC(HostWebGLContext::BindTexture)
|
DEFINE_ASYNC(HostWebGLContext::BindTexture)
|
||||||
DEFINE_ASYNC(HostWebGLContext::GenerateMipmap)
|
DEFINE_ASYNC(HostWebGLContext::GenerateMipmap)
|
||||||
DEFINE_ASYNC(HostWebGLContext::CopyTexImage)
|
DEFINE_ASYNC(HostWebGLContext::CopyTexImage)
|
||||||
DEFINE_ASYNC(HostWebGLContext::TexStorage)
|
DEFINE_ASYNC(HostWebGLContext::TexStorage)
|
||||||
// DEFINE_ASYNC(HostWebGLContext::TexImage)
|
DEFINE_ASYNC(HostWebGLContext::TexImage)
|
||||||
DEFINE_ASYNC(HostWebGLContext::CompressedTexImage)
|
DEFINE_ASYNC(HostWebGLContext::CompressedTexImage)
|
||||||
DEFINE_SYNC(HostWebGLContext::GetTexParameter)
|
DEFINE_SYNC(HostWebGLContext::GetTexParameter)
|
||||||
DEFINE_ASYNC(HostWebGLContext::TexParameter_base)
|
DEFINE_ASYNC(HostWebGLContext::TexParameter_base)
|
||||||
|
@ -144,7 +145,7 @@ DEFINE_SYNC(HostWebGLContext::GetVertexAttrib)
|
||||||
DEFINE_ASYNC(HostWebGLContext::VertexAttribPointer)
|
DEFINE_ASYNC(HostWebGLContext::VertexAttribPointer)
|
||||||
DEFINE_ASYNC(HostWebGLContext::ClearBufferTv)
|
DEFINE_ASYNC(HostWebGLContext::ClearBufferTv)
|
||||||
DEFINE_ASYNC(HostWebGLContext::ClearBufferfi)
|
DEFINE_ASYNC(HostWebGLContext::ClearBufferfi)
|
||||||
// DEFINE_SYNC(HostWebGLContext::ReadPixels)
|
DEFINE_SYNC(HostWebGLContext::ReadPixels)
|
||||||
DEFINE_ASYNC(HostWebGLContext::ReadPixelsPbo)
|
DEFINE_ASYNC(HostWebGLContext::ReadPixelsPbo)
|
||||||
DEFINE_ASYNC(HostWebGLContext::BindSampler)
|
DEFINE_ASYNC(HostWebGLContext::BindSampler)
|
||||||
DEFINE_ASYNC(HostWebGLContext::SamplerParameteri)
|
DEFINE_ASYNC(HostWebGLContext::SamplerParameteri)
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
|
|
||||||
#include "WebGLParent.h"
|
#include "WebGLParent.h"
|
||||||
|
|
||||||
#include "WebGLChild.h"
|
|
||||||
#include "mozilla/dom/WebGLCrossProcessCommandQueue.h"
|
#include "mozilla/dom/WebGLCrossProcessCommandQueue.h"
|
||||||
#include "mozilla/layers/LayerTransactionParent.h"
|
#include "mozilla/layers/LayerTransactionParent.h"
|
||||||
#include "mozilla/layers/TextureClientSharedSurface.h"
|
#include "mozilla/layers/TextureClientSharedSurface.h"
|
||||||
|
@ -15,31 +14,30 @@ namespace mozilla {
|
||||||
|
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
|
||||||
mozilla::ipc::IPCResult WebGLParent::RecvInitialize(
|
/* static */
|
||||||
const webgl::InitContextDesc& desc,
|
RefPtr<WebGLParent> WebGLParent::Create(const webgl::InitContextDesc& desc,
|
||||||
UniquePtr<HostWebGLCommandSinkP>&& aSinkP,
|
webgl::InitContextResult* const out) {
|
||||||
UniquePtr<HostWebGLCommandSinkI>&& aSinkI,
|
RefPtr<WebGLParent> parent = new WebGLParent;
|
||||||
webgl::InitContextResult* const out) {
|
|
||||||
auto remotingData = Some(HostWebGLContext::RemotingData{
|
auto remotingData = Some(HostWebGLContext::RemotingData{
|
||||||
*this, {}, // std::move(commandSink),
|
*parent, {}, // std::move(commandSink),
|
||||||
});
|
});
|
||||||
|
|
||||||
mHost = HostWebGLContext::Create(
|
parent->mHost = HostWebGLContext::Create(
|
||||||
{
|
{
|
||||||
{},
|
{},
|
||||||
std::move(remotingData),
|
std::move(remotingData),
|
||||||
},
|
},
|
||||||
desc, out);
|
desc, out);
|
||||||
|
|
||||||
if (!mHost) {
|
if (!parent->mHost) {
|
||||||
return IPC_FAIL(this, "Failed to create HostWebGLContext");
|
WEBGL_BRIDGE_LOGE("Failed to create HostWebGLContext");
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
if (!parent->BeginCommandQueueDrain()) {
|
||||||
if (!BeginCommandQueueDrain()) {
|
WEBGL_BRIDGE_LOGE("Failed to start WebGL command queue drain");
|
||||||
return IPC_FAIL(this, "Failed to start WebGL command queue drain");
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
return parent;
|
||||||
return IPC_OK();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WebGLParent::WebGLParent() = default;
|
WebGLParent::WebGLParent() = default;
|
||||||
|
|
|
@ -9,10 +9,10 @@
|
||||||
#include "mozilla/GfxMessageUtils.h"
|
#include "mozilla/GfxMessageUtils.h"
|
||||||
#include "mozilla/dom/PWebGLParent.h"
|
#include "mozilla/dom/PWebGLParent.h"
|
||||||
#include "mozilla/WeakPtr.h"
|
#include "mozilla/WeakPtr.h"
|
||||||
#include "mozilla/dom/IpdlQueue.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
|
class HostWebGLCommandSink;
|
||||||
class HostWebGLContext;
|
class HostWebGLContext;
|
||||||
|
|
||||||
namespace layers {
|
namespace layers {
|
||||||
|
@ -21,30 +21,21 @@ class SharedSurfaceTextureClient;
|
||||||
|
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
|
||||||
class WebGLParent : public PWebGLParent,
|
class WebGLParent final : public PWebGLParent,
|
||||||
public AsyncProducerActor<WebGLParent>,
|
public SupportsWeakPtr<WebGLParent> {
|
||||||
public SyncConsumerActor<WebGLParent>,
|
|
||||||
public SupportsWeakPtr<WebGLParent> {
|
|
||||||
friend PWebGLParent;
|
friend PWebGLParent;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebGLParent, override);
|
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebGLParent, override);
|
||||||
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(WebGLParent)
|
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(WebGLParent)
|
||||||
using OtherSideActor = WebGLChild;
|
|
||||||
|
|
||||||
mozilla::ipc::IPCResult RecvInitialize(
|
static RefPtr<WebGLParent> Create(const webgl::InitContextDesc&,
|
||||||
const webgl::InitContextDesc&, UniquePtr<HostWebGLCommandSinkP>&& aSinkP,
|
webgl::InitContextResult* out);
|
||||||
UniquePtr<HostWebGLCommandSinkI>&& aSinkI, webgl::InitContextResult* out);
|
|
||||||
|
|
||||||
RefPtr<layers::SharedSurfaceTextureClient> GetVRFrame(webgl::ObjectId);
|
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:
|
private:
|
||||||
|
WebGLParent();
|
||||||
~WebGLParent();
|
~WebGLParent();
|
||||||
|
|
||||||
bool BeginCommandQueueDrain();
|
bool BeginCommandQueueDrain();
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#ifndef WEBGLQUEUEPARAMTRAITS_H_
|
#ifndef WEBGLPCQPARAMTRAITS_H_
|
||||||
#define WEBGLQUEUEPARAMTRAITS_H_
|
#define WEBGLPCQPARAMTRAITS_H_
|
||||||
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ namespace mozilla {
|
||||||
|
|
||||||
namespace webgl {
|
namespace webgl {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct QueueParamTraits;
|
struct PcqParamTraits;
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct IsTriviallySerializable<FloatOrInt> : std::true_type {};
|
struct IsTriviallySerializable<FloatOrInt> : std::true_type {};
|
||||||
|
@ -56,21 +56,12 @@ struct IsTriviallySerializable<avec3<T>> : std::true_type {};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct IsTriviallySerializable<webgl::TexUnpackBlob> : std::true_type {};
|
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 <>
|
template <>
|
||||||
struct QueueParamTraits<WebGLActiveInfo> {
|
struct PcqParamTraits<WebGLActiveInfo> {
|
||||||
using ParamType = 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.mElemCount);
|
||||||
aProducerView.WriteParam(aArg.mElemType);
|
aProducerView.WriteParam(aArg.mElemType);
|
||||||
aProducerView.WriteParam(aArg.mBaseUserName);
|
aProducerView.WriteParam(aArg.mBaseUserName);
|
||||||
|
@ -80,7 +71,7 @@ struct QueueParamTraits<WebGLActiveInfo> {
|
||||||
return aProducerView.WriteParam(aArg.mBaseType);
|
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->mElemCount : nullptr);
|
||||||
aConsumerView.ReadParam(aArg ? &aArg->mElemType : nullptr);
|
aConsumerView.ReadParam(aArg ? &aArg->mElemType : nullptr);
|
||||||
aConsumerView.ReadParam(aArg ? &aArg->mBaseUserName : nullptr);
|
aConsumerView.ReadParam(aArg ? &aArg->mBaseUserName : nullptr);
|
||||||
|
@ -103,23 +94,21 @@ struct QueueParamTraits<WebGLActiveInfo> {
|
||||||
};
|
};
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct QueueParamTraits<RawBuffer<T>> {
|
struct PcqParamTraits<RawBuffer<T>> {
|
||||||
using ParamType = RawBuffer<T>;
|
using ParamType = RawBuffer<T>;
|
||||||
|
|
||||||
template <typename U>
|
static PcqStatus Write(ProducerView& aProducerView, const ParamType& aArg) {
|
||||||
static QueueStatus Write(ProducerView<U>& aProducerView,
|
|
||||||
const ParamType& aArg) {
|
|
||||||
aProducerView.WriteParam(aArg.mLength);
|
aProducerView.WriteParam(aArg.mLength);
|
||||||
return (aArg.mLength > 0)
|
return (aArg.mLength > 0)
|
||||||
? aProducerView.Write(aArg.mData, aArg.mLength * sizeof(T))
|
? aProducerView.Write(aArg.mData, aArg.mLength * sizeof(T))
|
||||||
: aProducerView.GetStatus();
|
: aProducerView.Status();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename U, typename ElementType = typename std::remove_cv_t<
|
template <
|
||||||
typename ParamType::ElementType>>
|
typename ElementType = std::remove_cv_t<typename ParamType::ElementType>>
|
||||||
static QueueStatus Read(ConsumerView<U>& aConsumerView, ParamType* aArg) {
|
static PcqStatus Read(ConsumerView& aConsumerView, ParamType* aArg) {
|
||||||
size_t len;
|
size_t len;
|
||||||
QueueStatus status = aConsumerView.ReadParam(&len);
|
PcqStatus status = aConsumerView.ReadParam(&len);
|
||||||
if (!status) {
|
if (!status) {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -129,7 +118,7 @@ struct QueueParamTraits<RawBuffer<T>> {
|
||||||
aArg->mLength = 0;
|
aArg->mLength = 0;
|
||||||
aArg->mData = nullptr;
|
aArg->mData = nullptr;
|
||||||
}
|
}
|
||||||
return QueueStatus::kSuccess;
|
return PcqStatus::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!aArg) {
|
if (!aArg) {
|
||||||
|
@ -137,17 +126,17 @@ struct QueueParamTraits<RawBuffer<T>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RawBufferReadMatcher {
|
struct RawBufferReadMatcher {
|
||||||
QueueStatus operator()(RefPtr<mozilla::ipc::SharedMemoryBasic>& smem) {
|
PcqStatus operator()(RefPtr<mozilla::ipc::SharedMemoryBasic>& smem) {
|
||||||
if (!smem) {
|
if (!smem) {
|
||||||
return QueueStatus::kFatalError;
|
return PcqStatus::PcqFatalError;
|
||||||
}
|
}
|
||||||
mArg->mSmem = smem;
|
mArg->mSmem = smem;
|
||||||
mArg->mData = static_cast<ElementType*>(smem->memory());
|
mArg->mData = static_cast<ElementType*>(smem->memory());
|
||||||
mArg->mLength = mLength;
|
mArg->mLength = mLength;
|
||||||
mArg->mOwnsData = false;
|
mArg->mOwnsData = false;
|
||||||
return QueueStatus::kSuccess;
|
return PcqStatus::Success;
|
||||||
}
|
}
|
||||||
QueueStatus operator()() {
|
PcqStatus operator()() {
|
||||||
mArg->mSmem = nullptr;
|
mArg->mSmem = nullptr;
|
||||||
ElementType* buf = new ElementType[mLength];
|
ElementType* buf = new ElementType[mLength];
|
||||||
mArg->mData = buf;
|
mArg->mData = buf;
|
||||||
|
@ -156,7 +145,7 @@ struct QueueParamTraits<RawBuffer<T>> {
|
||||||
return mConsumerView.Read(buf, mLength * sizeof(T));
|
return mConsumerView.Read(buf, mLength * sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
ConsumerView<U>& mConsumerView;
|
ConsumerView& mConsumerView;
|
||||||
ParamType* mArg;
|
ParamType* mArg;
|
||||||
size_t mLength;
|
size_t mLength;
|
||||||
};
|
};
|
||||||
|
@ -176,16 +165,16 @@ struct QueueParamTraits<RawBuffer<T>> {
|
||||||
enum TexUnpackTypes : uint8_t { Bytes, Surface, Image, Pbo };
|
enum TexUnpackTypes : uint8_t { Bytes, Surface, Image, Pbo };
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct QueueParamTraits<webgl::TexUnpackBytes> {
|
struct PcqParamTraits<webgl::TexUnpackBytes> {
|
||||||
using ParamType = 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.
|
// Write TexUnpackBlob base class, then the RawBuffer.
|
||||||
aProducerView.WriteParam(static_cast<const webgl::TexUnpackBlob&>(aArg));
|
aProducerView.WriteParam(static_cast<const webgl::TexUnpackBlob&>(aArg));
|
||||||
return aProducerView.WriteParam(aArg.mPtr);
|
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.
|
// Read TexUnpackBlob base class, then the RawBuffer.
|
||||||
aConsumerView.ReadParam(static_cast<webgl::TexUnpackBlob*>(aArg));
|
aConsumerView.ReadParam(static_cast<webgl::TexUnpackBlob*>(aArg));
|
||||||
return aConsumerView.ReadParam(aArg ? &aArg->mPtr : nullptr);
|
return aConsumerView.ReadParam(aArg ? &aArg->mPtr : nullptr);
|
||||||
|
@ -199,10 +188,10 @@ struct QueueParamTraits<webgl::TexUnpackBytes> {
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct QueueParamTraits<webgl::TexUnpackSurface> {
|
struct PcqParamTraits<webgl::TexUnpackSurface> {
|
||||||
using ParamType = 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(static_cast<const webgl::TexUnpackBlob&>(aArg));
|
||||||
aProducerView.WriteParam(aArg.mSize);
|
aProducerView.WriteParam(aArg.mSize);
|
||||||
aProducerView.WriteParam(aArg.mFormat);
|
aProducerView.WriteParam(aArg.mFormat);
|
||||||
|
@ -210,7 +199,7 @@ struct QueueParamTraits<webgl::TexUnpackSurface> {
|
||||||
return aProducerView.WriteParam(aArg.mStride);
|
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(static_cast<webgl::TexUnpackBlob*>(aArg));
|
||||||
aConsumerView.ReadParam(aArg ? &aArg->mSize : nullptr);
|
aConsumerView.ReadParam(aArg ? &aArg->mSize : nullptr);
|
||||||
aConsumerView.ReadParam(aArg ? &aArg->mFormat : 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
|
// efficiently convert types. For example, a TexUnpackSurface may deserialize
|
||||||
// as a TexUnpackBytes.
|
// as a TexUnpackBytes.
|
||||||
template <>
|
template <>
|
||||||
struct QueueParamTraits<WebGLTexUnpackVariant> {
|
struct PcqParamTraits<WebGLTexUnpackVariant> {
|
||||||
using ParamType = WebGLTexUnpackVariant;
|
using ParamType = WebGLTexUnpackVariant;
|
||||||
|
|
||||||
static QueueStatus Write(ProducerView& aProducerView, const ParamType& aArg) {
|
static PcqStatus Write(ProducerView& aProducerView, const ParamType& aArg) {
|
||||||
struct TexUnpackWriteMatcher {
|
struct TexUnpackWriteMatcher {
|
||||||
QueueStatus operator()(const UniquePtr<webgl::TexUnpackBytes>& x) {
|
PcqStatus operator()(const UniquePtr<webgl::TexUnpackBytes>& x) {
|
||||||
mProducerView.WriteParam(TexUnpackTypes::Bytes);
|
mProducerView.WriteParam(TexUnpackTypes::Bytes);
|
||||||
return mProducerView.WriteParam(x);
|
return mProducerView.WriteParam(x);
|
||||||
}
|
}
|
||||||
QueueStatus operator()(const UniquePtr<webgl::TexUnpackSurface>& x) {
|
PcqStatus operator()(const UniquePtr<webgl::TexUnpackSurface>& x) {
|
||||||
mProducerView.WriteParam(TexUnpackTypes::Surface);
|
mProducerView.WriteParam(TexUnpackTypes::Surface);
|
||||||
return mProducerView.WriteParam(x);
|
return mProducerView.WriteParam(x);
|
||||||
}
|
}
|
||||||
QueueStatus operator()(const UniquePtr<webgl::TexUnpackImage>& x) {
|
PcqStatus operator()(const UniquePtr<webgl::TexUnpackImage>& x) {
|
||||||
MOZ_ASSERT_UNREACHABLE("TODO:");
|
MOZ_ASSERT_UNREACHABLE("TODO:");
|
||||||
return QueueStatus::kFatalError;
|
return PcqStatus::PcqFatalError;
|
||||||
}
|
}
|
||||||
QueueStatus operator()(const WebGLTexPboOffset& x) {
|
PcqStatus operator()(const WebGLTexPboOffset& x) {
|
||||||
mProducerView.WriteParam(TexUnpackTypes::Pbo);
|
mProducerView.WriteParam(TexUnpackTypes::Pbo);
|
||||||
return mProducerView.WriteParam(x);
|
return mProducerView.WriteParam(x);
|
||||||
}
|
}
|
||||||
|
@ -258,14 +247,14 @@ struct QueueParamTraits<WebGLTexUnpackVariant> {
|
||||||
return aArg.match(TexUnpackWriteMatcher{aProducerView});
|
return aArg.match(TexUnpackWriteMatcher{aProducerView});
|
||||||
}
|
}
|
||||||
|
|
||||||
static QueueStatus Read(ConsumerView& aConsumerView, ParamType* aArg) {
|
static PcqStatus Read(ConsumerView& aConsumerView, ParamType* aArg) {
|
||||||
if (!aArg) {
|
if (!aArg) {
|
||||||
// Not a great estimate but we can't do much better.
|
// Not a great estimate but we can't do much better.
|
||||||
return aConsumerView.template ReadParam<TexUnpackTypes>();
|
return aConsumerView.template ReadParam<TexUnpackTypes>();
|
||||||
}
|
}
|
||||||
TexUnpackTypes unpackType;
|
TexUnpackTypes unpackType;
|
||||||
if (!aConsumerView.ReadParam(&unpackType)) {
|
if (!aConsumerView.ReadParam(&unpackType)) {
|
||||||
return aConsumerView.GetStatus();
|
return aConsumerView.Status();
|
||||||
}
|
}
|
||||||
switch (unpackType) {
|
switch (unpackType) {
|
||||||
case TexUnpackTypes::Bytes:
|
case TexUnpackTypes::Bytes:
|
||||||
|
@ -278,13 +267,13 @@ struct QueueParamTraits<WebGLTexUnpackVariant> {
|
||||||
&aArg->as<UniquePtr<webgl::TexUnpackSurface>>());
|
&aArg->as<UniquePtr<webgl::TexUnpackSurface>>());
|
||||||
case TexUnpackTypes::Image:
|
case TexUnpackTypes::Image:
|
||||||
MOZ_ASSERT_UNREACHABLE("TODO:");
|
MOZ_ASSERT_UNREACHABLE("TODO:");
|
||||||
return QueueStatus::kFatalError;
|
return PcqStatus::PcqFatalError;
|
||||||
case TexUnpackTypes::Pbo:
|
case TexUnpackTypes::Pbo:
|
||||||
*aArg = AsVariant(WebGLTexPboOffset());
|
*aArg = AsVariant(WebGLTexPboOffset());
|
||||||
return aConsumerView.ReadParam(&aArg->as<WebGLTexPboOffset>());
|
return aConsumerView.ReadParam(&aArg->as<WebGLTexPboOffset>());
|
||||||
}
|
}
|
||||||
MOZ_ASSERT_UNREACHABLE("Illegal texture unpack type");
|
MOZ_ASSERT_UNREACHABLE("Illegal texture unpack type");
|
||||||
return QueueStatus::kFatalError;
|
return PcqStatus::PcqFatalError;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename View>
|
template <typename View>
|
||||||
|
@ -315,23 +304,20 @@ struct QueueParamTraits<WebGLTexUnpackVariant> {
|
||||||
};
|
};
|
||||||
*/
|
*/
|
||||||
template <>
|
template <>
|
||||||
struct QueueParamTraits<webgl::ContextLossReason> {
|
struct PcqParamTraits<webgl::ContextLossReason> {
|
||||||
using ParamType = webgl::ContextLossReason;
|
using ParamType = webgl::ContextLossReason;
|
||||||
|
|
||||||
template <typename U>
|
static PcqStatus Write(ProducerView& aProducerView, const ParamType& aArg) {
|
||||||
static QueueStatus Write(ProducerView<U>& aProducerView,
|
|
||||||
const ParamType& aArg) {
|
|
||||||
return aProducerView.WriteParam(static_cast<uint8_t>(aArg));
|
return aProducerView.WriteParam(static_cast<uint8_t>(aArg));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename U>
|
static PcqStatus Read(ConsumerView& aConsumerView, ParamType* aArg) {
|
||||||
static QueueStatus Read(ConsumerView<U>& aConsumerView, ParamType* aArg) {
|
|
||||||
uint8_t val;
|
uint8_t val;
|
||||||
auto status = aConsumerView.ReadParam(&val);
|
auto status = aConsumerView.ReadParam(&val);
|
||||||
if (!status) return status;
|
if (!status) return status;
|
||||||
if (!ReadContextLossReason(val, aArg)) {
|
if (!ReadContextLossReason(val, aArg)) {
|
||||||
MOZ_ASSERT_UNREACHABLE("Invalid ContextLossReason");
|
MOZ_ASSERT_UNREACHABLE("Invalid ContextLossReason");
|
||||||
return QueueStatus::kFatalError;
|
return PcqStatus::PcqFatalError;
|
||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -343,11 +329,10 @@ struct QueueParamTraits<webgl::ContextLossReason> {
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename V, typename E>
|
template <typename V, typename E>
|
||||||
struct QueueParamTraits<Result<V, E>> {
|
struct PcqParamTraits<Result<V, E>> {
|
||||||
using T = Result<V, E>;
|
using T = Result<V, E>;
|
||||||
|
|
||||||
template <typename U>
|
static PcqStatus Write(ProducerView& aProducerView, const T& aArg) {
|
||||||
static QueueStatus Write(ProducerView<U>& aProducerView, const T& aArg) {
|
|
||||||
const auto ok = aArg.isOk();
|
const auto ok = aArg.isOk();
|
||||||
auto status = aProducerView.WriteParam(ok);
|
auto status = aProducerView.WriteParam(ok);
|
||||||
if (!status) return status;
|
if (!status) return status;
|
||||||
|
@ -359,8 +344,7 @@ struct QueueParamTraits<Result<V, E>> {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename U>
|
static PcqStatus Read(ConsumerView& aConsumerView, T* const aArg) {
|
||||||
static QueueStatus Read(ConsumerView<U>& aConsumerView, T* const aArg) {
|
|
||||||
bool ok;
|
bool ok;
|
||||||
auto status = aConsumerView.ReadParam(&ok);
|
auto status = aConsumerView.ReadParam(&ok);
|
||||||
if (!status) return status;
|
if (!status) return status;
|
||||||
|
@ -393,26 +377,24 @@ struct QueueParamTraits<Result<V, E>> {
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct QueueParamTraits<std::string> {
|
struct PcqParamTraits<std::string> {
|
||||||
using T = std::string;
|
using T = std::string;
|
||||||
|
|
||||||
template <typename U>
|
static PcqStatus Write(ProducerView& aProducerView, const T& aArg) {
|
||||||
static QueueStatus Write(ProducerView<U>& aProducerView, const T& aArg) {
|
|
||||||
auto status = aProducerView.WriteParam(aArg.size());
|
auto status = aProducerView.WriteParam(aArg.size());
|
||||||
if (!status) return status;
|
if (!status) return status;
|
||||||
status = aProducerView.Write(aArg.data(), aArg.size());
|
status = aProducerView.Write(aArg.data(), aArg.size());
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename U>
|
static PcqStatus Read(ConsumerView& aConsumerView, T* const aArg) {
|
||||||
static QueueStatus Read(ConsumerView<U>& aConsumerView, T* const aArg) {
|
|
||||||
size_t size;
|
size_t size;
|
||||||
auto status = aConsumerView.ReadParam(&size);
|
auto status = aConsumerView.ReadParam(&size);
|
||||||
if (!status) return status;
|
if (!status) return status;
|
||||||
|
|
||||||
const UniqueBuffer temp = malloc(size);
|
const UniqueBuffer temp = malloc(size);
|
||||||
const auto dest = static_cast<char*>(temp.get());
|
const auto dest = static_cast<char*>(temp.get());
|
||||||
if (!dest) return QueueStatus::kFatalError;
|
if (!dest) return PcqStatus::PcqFatalError;
|
||||||
|
|
||||||
status = aConsumerView.Read(dest, size);
|
status = aConsumerView.Read(dest, size);
|
||||||
if (aArg) {
|
if (aArg) {
|
||||||
|
@ -432,19 +414,17 @@ struct QueueParamTraits<std::string> {
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename U>
|
template <typename U>
|
||||||
struct QueueParamTraits<std::vector<U>> {
|
struct PcqParamTraits<std::vector<U>> {
|
||||||
using T = std::vector<U>;
|
using T = std::string;
|
||||||
|
|
||||||
template <typename V>
|
static PcqStatus Write(ProducerView& aProducerView, const T& aArg) {
|
||||||
static QueueStatus Write(ProducerView<V>& aProducerView, const T& aArg) {
|
|
||||||
auto status = aProducerView.WriteParam(aArg.size());
|
auto status = aProducerView.WriteParam(aArg.size());
|
||||||
if (!status) return status;
|
if (!status) return status;
|
||||||
status = aProducerView.Write(aArg.data(), aArg.size());
|
status = aProducerView.Write(aArg.data(), aArg.size());
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename V>
|
static PcqStatus Read(ConsumerView& aConsumerView, T* const aArg) {
|
||||||
static QueueStatus Read(ConsumerView<V>& aConsumerView, T* const aArg) {
|
|
||||||
MOZ_CRASH("no way to fallibly resize vectors without exceptions");
|
MOZ_CRASH("no way to fallibly resize vectors without exceptions");
|
||||||
size_t size;
|
size_t size;
|
||||||
auto status = aConsumerView.ReadParam(&size);
|
auto status = aConsumerView.ReadParam(&size);
|
||||||
|
@ -466,23 +446,21 @@ struct QueueParamTraits<std::vector<U>> {
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct QueueParamTraits<WebGLExtensionID> {
|
struct PcqParamTraits<WebGLExtensionID> {
|
||||||
using T = WebGLExtensionID;
|
using T = WebGLExtensionID;
|
||||||
|
|
||||||
template <typename U>
|
static PcqStatus Write(ProducerView& aProducerView, const T& aArg) {
|
||||||
static QueueStatus Write(ProducerView<U>& aProducerView, const T& aArg) {
|
|
||||||
return aProducerView.WriteParam(mozilla::EnumValue(aArg));
|
return aProducerView.WriteParam(mozilla::EnumValue(aArg));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename U>
|
static PcqStatus Read(ConsumerView& aConsumerView, T* const aArg) {
|
||||||
static QueueStatus Read(ConsumerView<U>& aConsumerView, T* const aArg) {
|
PcqStatus status = PcqStatus::Success;
|
||||||
QueueStatus status = QueueStatus::kSuccess;
|
|
||||||
if (aArg) {
|
if (aArg) {
|
||||||
status = aConsumerView.ReadParam(
|
status = aConsumerView.ReadParam(
|
||||||
reinterpret_cast<typename std::underlying_type<T>::type*>(aArg));
|
reinterpret_cast<typename std::underlying_type<T>::type*>(aArg));
|
||||||
if (*aArg >= WebGLExtensionID::Max) {
|
if (*aArg >= WebGLExtensionID::Max) {
|
||||||
MOZ_ASSERT(false);
|
MOZ_ASSERT(false);
|
||||||
return QueueStatus::kFatalError;
|
return PcqStatus::PcqFatalError;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return status;
|
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 webgl
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
||||||
#endif // WEBGLQUEUEPARAMTRAITS_H_
|
#endif // WEBGLPCQPARAMTRAITS_H_
|
|
@ -94,9 +94,12 @@ inline auto AutoAssertCast(const From val) {
|
||||||
return detail::AutoAssertCastT<From>(val);
|
return detail::AutoAssertCastT<From>(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace webgl {
|
namespace ipc {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct QueueParamTraits;
|
struct PcqParamTraits;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace webgl {
|
||||||
class TexUnpackBytes;
|
class TexUnpackBytes;
|
||||||
class TexUnpackImage;
|
class TexUnpackImage;
|
||||||
class TexUnpackSurface;
|
class TexUnpackSurface;
|
||||||
|
@ -730,7 +733,7 @@ class RawBuffer {
|
||||||
// true if we should delete[] the mData on destruction
|
// true if we should delete[] the mData on destruction
|
||||||
bool mOwnsData = false;
|
bool mOwnsData = false;
|
||||||
|
|
||||||
friend struct mozilla::webgl::QueueParamTraits<RawBuffer<T>>;
|
friend mozilla::ipc::PcqParamTraits<RawBuffer>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using ElementType = T;
|
using ElementType = T;
|
||||||
|
|
|
@ -58,10 +58,8 @@ EXPORTS.mozilla.dom += [
|
||||||
'ImageBitmapSource.h',
|
'ImageBitmapSource.h',
|
||||||
'ImageData.h',
|
'ImageData.h',
|
||||||
'ImageUtils.h',
|
'ImageUtils.h',
|
||||||
'IpdlQueue.h',
|
|
||||||
'OffscreenCanvas.h',
|
'OffscreenCanvas.h',
|
||||||
'ProducerConsumerQueue.h',
|
'ProducerConsumerQueue.h',
|
||||||
'QueueParamTraits.h',
|
|
||||||
'TextMetrics.h',
|
'TextMetrics.h',
|
||||||
'WebGLChild.h',
|
'WebGLChild.h',
|
||||||
'WebGLCommandQueue.h',
|
'WebGLCommandQueue.h',
|
||||||
|
@ -96,7 +94,7 @@ UNIFIED_SOURCES += [
|
||||||
'ClientWebGLContext.cpp',
|
'ClientWebGLContext.cpp',
|
||||||
'ClientWebGLExtensions.cpp',
|
'ClientWebGLExtensions.cpp',
|
||||||
'HostWebGLContext.cpp',
|
'HostWebGLContext.cpp',
|
||||||
'Queue.cpp',
|
'ProducerConsumerQueue.cpp',
|
||||||
'TexUnpackBlob.cpp',
|
'TexUnpackBlob.cpp',
|
||||||
'WebGL2Context.cpp',
|
'WebGL2Context.cpp',
|
||||||
'WebGL2ContextBuffers.cpp',
|
'WebGL2ContextBuffers.cpp',
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "base/message_loop.h" // for MessageLoop
|
#include "base/message_loop.h" // for MessageLoop
|
||||||
#include "base/task.h" // for NewRunnableMethod, etc
|
#include "base/task.h" // for NewRunnableMethod, etc
|
||||||
#include "mozilla/StaticPrefs_layers.h"
|
#include "mozilla/StaticPrefs_layers.h"
|
||||||
|
#include "mozilla/dom/WebGLChild.h"
|
||||||
#include "mozilla/layers/CompositorManagerChild.h"
|
#include "mozilla/layers/CompositorManagerChild.h"
|
||||||
#include "mozilla/layers/ImageBridgeChild.h"
|
#include "mozilla/layers/ImageBridgeChild.h"
|
||||||
#include "mozilla/layers/APZChild.h"
|
#include "mozilla/layers/APZChild.h"
|
||||||
|
|
|
@ -53,6 +53,7 @@ class nsIWidget;
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
class CancelableRunnable;
|
class CancelableRunnable;
|
||||||
|
class HostWebGLCommandSink;
|
||||||
|
|
||||||
namespace dom {
|
namespace dom {
|
||||||
class WebGLParent;
|
class WebGLParent;
|
||||||
|
@ -302,7 +303,8 @@ class CompositorBridgeParentBase : public PCompositorBridgeParent,
|
||||||
return IPC_FAIL_NO_REASON(this);
|
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;
|
bool mCanSend;
|
||||||
|
|
||||||
|
@ -692,7 +694,8 @@ class CompositorBridgeParent final : public CompositorBridgeParentBase,
|
||||||
WebRenderBridgeParent* GetWrBridge() { return mWrBridge; }
|
WebRenderBridgeParent* GetWrBridge() { return mWrBridge; }
|
||||||
webgpu::WebGPUParent* GetWebGPUBridge() { return mWebGPUBridge; }
|
webgpu::WebGPUParent* GetWebGPUBridge() { return mWebGPUBridge; }
|
||||||
|
|
||||||
already_AddRefed<PWebGLParent> AllocPWebGLParent() override {
|
already_AddRefed<PWebGLParent> AllocPWebGLParent(
|
||||||
|
const webgl::InitContextDesc&, webgl::InitContextResult*) override {
|
||||||
MOZ_ASSERT_UNREACHABLE(
|
MOZ_ASSERT_UNREACHABLE(
|
||||||
"This message is CrossProcessCompositorBridgeParent only");
|
"This message is CrossProcessCompositorBridgeParent only");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
@ -766,9 +766,11 @@ mozilla::ipc::IPCResult ContentCompositorBridgeParent::RecvPreferredDXGIAdapter(
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<dom::PWebGLParent>
|
already_AddRefed<dom::PWebGLParent>
|
||||||
ContentCompositorBridgeParent::AllocPWebGLParent() {
|
ContentCompositorBridgeParent::AllocPWebGLParent(
|
||||||
RefPtr<dom::PWebGLParent> parent = new dom::WebGLParent();
|
const webgl::InitContextDesc& aInitDesc,
|
||||||
return parent.forget();
|
webgl::InitContextResult* const out) {
|
||||||
|
RefPtr<dom::PWebGLParent> ret = dom::WebGLParent::Create(aInitDesc, out);
|
||||||
|
return ret.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace layers
|
} // namespace layers
|
||||||
|
|
|
@ -161,7 +161,8 @@ class ContentCompositorBridgeParent final : public CompositorBridgeParentBase {
|
||||||
return IPC_FAIL_NO_REASON(this);
|
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
|
// Use DidCompositeLocked if you already hold a lock on
|
||||||
// sIndirectLayerTreesLock; Otherwise use DidComposite, which would request
|
// 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::LayersObserverEpoch from "mozilla/layers/LayersTypes.h";
|
||||||
using mozilla::layers::TransactionId from "mozilla/layers/LayersTypes.h";
|
using mozilla::layers::TransactionId from "mozilla/layers/LayersTypes.h";
|
||||||
using struct DxgiAdapterDesc from "mozilla/D3DMessageUtils.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 mozilla {
|
||||||
namespace layers {
|
namespace layers {
|
||||||
|
@ -298,7 +300,9 @@ parent:
|
||||||
async RequestFxrOutput();
|
async RequestFxrOutput();
|
||||||
|
|
||||||
// Actor that represents one WebGL context.
|
// Actor that represents one WebGL context.
|
||||||
async PWebGL();
|
// (modeled after `sync PBackgroundLSSnapshot`)
|
||||||
|
sync PWebGL(InitContextDesc desc)
|
||||||
|
returns (InitContextResult res);
|
||||||
|
|
||||||
child:
|
child:
|
||||||
// Send back Compositor Frame Metrics from APZCs so tiled layers can
|
// 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.
|
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]
|
[PWebGL::UpdateCompositableHandle]
|
||||||
description = Compositing WebGL is synchronous by spec. Updates to WebGL canvas contents must be updated in lockstep with other DOM updates.
|
description = Compositing WebGL is synchronous by spec. Updates to WebGL canvas contents must be updated in lockstep with other DOM updates.
|
||||||
[PWebGL::Initialize]
|
[PCompositorBridge::PWebGL]
|
||||||
description = Initialization of WebGL contexts is synchronous by spec.
|
description = Creation 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.
|
|
||||||
[PSocketProcess::GetTLSClientCert]
|
[PSocketProcess::GetTLSClientCert]
|
||||||
description = Synchronously get client certificate and key from parent process. Once bug 696976 has been fixed, this can be removed.
|
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
|
value: true
|
||||||
mirror: always
|
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."
|
# Prefs starting with "widget."
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
|
|
Загрузка…
Ссылка в новой задаче