Bug 1691606 - Clean up dead code following WebGL out-of-process stabilization. r=lsalzman

Differential Revision: https://phabricator.services.mozilla.com/D104495
This commit is contained in:
Jeff Gilbert 2021-02-09 07:57:03 +00:00
Родитель b850ece2f9
Коммит 09bc72760a
16 изменённых файлов: 77 добавлений и 1926 удалений

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

@ -41,8 +41,7 @@ webgl::NotLostData::NotLostData(ClientWebGLContext& _context)
webgl::NotLostData::~NotLostData() {
if (outOfProcess) {
const auto& pwebgl = outOfProcess->mWebGLChild;
Unused << dom::WebGLChild::Send__delete__(pwebgl.get());
Unused << dom::WebGLChild::Send__delete__(outOfProcess.get());
}
}
@ -212,7 +211,6 @@ void ClientWebGLContext::OnContextLoss(
}
void ClientWebGLContext::Event_webglcontextlost() const {
WEBGL_BRIDGE_LOGD("[%p] Posting webglcontextlost event", this);
const bool useDefaultHandler = DispatchEvent(u"webglcontextlost"_ns);
if (useDefaultHandler) {
mLossStatus = webgl::LossStatus::LostForever;
@ -263,7 +261,6 @@ void ClientWebGLContext::Event_webglcontextrestored() const {
return;
}
WEBGL_BRIDGE_LOGD("[%p] Posting webglcontextrestored event", this);
(void)DispatchEvent(u"webglcontextrestored"_ns);
}
@ -282,7 +279,6 @@ void ClientWebGLContext::ThrowEvent_WebGLContextCreationError(
return;
}
WEBGL_BRIDGE_LOGD("[%p] Posting webglcontextcreationerror event", this);
const auto kEventName = u"webglcontextcreationerror"_ns;
dom::WebGLContextEventInit eventInit;
@ -311,7 +307,7 @@ void ClientWebGLContext::Run(Args&&... args) const {
return (inProcess.get()->*method)(std::forward<Args>(args)...);
}
const auto& child = notLost->outOfProcess->mWebGLChild;
const auto& child = notLost->outOfProcess;
const auto id = IdByMethod<MethodType, method>();
@ -371,7 +367,7 @@ Maybe<layers::SurfaceDescriptor> ClientWebGLContext::GetFrontBuffer(
return inProcess->GetFrontBuffer(fb ? fb->mId : 0, vr);
}
const auto& child = mNotLost->outOfProcess->mWebGLChild;
const auto& child = mNotLost->outOfProcess;
child->FlushPendingCmds();
Maybe<layers::SurfaceDescriptor> ret;
if (!child->SendGetFrontBuffer(fb ? fb->mId : 0, vr, &ret)) return {};
@ -389,8 +385,6 @@ already_AddRefed<layers::Layer> ClientWebGLContext::GetCanvasLayer(
return ret.forget();
}
WEBGL_BRIDGE_LOGI("[%p] Creating WebGL CanvasLayer/Renderer", this);
RefPtr<CanvasLayer> canvasLayer = manager->CreateCanvasLayer();
if (!canvasLayer) {
NS_WARNING("CreateCanvasLayer returned null!");
@ -418,7 +412,6 @@ bool ClientWebGLContext::UpdateWebRenderCanvasData(
return true;
}
WEBGL_BRIDGE_LOGI("[%p] Creating WebGL WR CanvasLayer/Renderer", this);
renderer = aCanvasData->CreateCanvasRenderer();
if (!InitializeCanvasRenderer(aBuilder, renderer)) {
// Clear CanvasRenderer of WebRenderCanvasData
@ -522,9 +515,6 @@ NS_IMETHODIMP
ClientWebGLContext::SetDimensions(const int32_t signedWidth,
const int32_t signedHeight) {
const FuncScope funcScope(*this, "<SetDimensions>");
WEBGL_BRIDGE_LOGI("[%p] SetDimensions: (%d, %d)", this, signedWidth,
signedHeight);
MOZ_ASSERT(mInitialOptions);
if (mLossStatus != webgl::LossStatus::Ready) {
@ -626,10 +616,7 @@ bool ClientWebGLContext::CreateHostContext(const uvec2& requestedSize) {
}
if (!useOop) {
auto ownerData = HostWebGLContext::OwnerData{
Some(this),
};
notLost.inProcess = HostWebGLContext::Create(std::move(ownerData),
notLost.inProcess = HostWebGLContext::Create({this, nullptr},
initDesc, &notLost.info);
return Ok();
}
@ -638,61 +625,25 @@ bool ClientWebGLContext::CreateHostContext(const uvec2& requestedSize) {
ScopedGfxFeatureReporter reporter("IpcWebGL");
webgl::RemotingData outOfProcess;
auto* const cbc = layers::CompositorBridgeChild::Get();
MOZ_ASSERT(cbc);
if (!cbc) {
return Err("!CompositorBridgeChild::Get()");
}
outOfProcess.mWebGLChild = new dom::WebGLChild(*this);
outOfProcess.mWebGLChild = static_cast<dom::WebGLChild*>(
cbc->SendPWebGLConstructor(outOfProcess.mWebGLChild));
if (!outOfProcess.mWebGLChild) {
RefPtr<dom::WebGLChild> outOfProcess = new dom::WebGLChild(*this);
outOfProcess = static_cast<dom::WebGLChild*>(
cbc->SendPWebGLConstructor(outOfProcess));
if (!outOfProcess) {
return Err("SendPWebGLConstructor failed");
}
UniquePtr<HostWebGLCommandSinkP> sinkP;
UniquePtr<HostWebGLCommandSinkI> sinkI;
if (StaticPrefs::webgl_oop_via_pcq()) {
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());
} else {
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());
}
if (!outOfProcess.mWebGLChild->SendInitialize(
initDesc, std::move(sinkP), std::move(sinkI), &notLost.info)) {
if (!outOfProcess->SendInitialize(
initDesc, &notLost.info)) {
return Err("WebGL actor Initialize failed");
}
notLost.outOfProcess = Some(std::move(outOfProcess));
notLost.outOfProcess = outOfProcess;
reporter.SetSuccessful();
return Ok();
}();
@ -771,7 +722,7 @@ uvec2 ClientWebGLContext::DrawingBufferSize() {
if (inProcess) {
size = Some(inProcess->DrawingBufferSize());
} else {
const auto& child = mNotLost->outOfProcess->mWebGLChild;
const auto& child = mNotLost->outOfProcess;
child->FlushPendingCmds();
uvec2 actual = {};
if (!child->SendDrawingBufferSize(&actual)) return {};
@ -789,7 +740,7 @@ void ClientWebGLContext::OnMemoryPressure() {
if (inProcess) {
return inProcess->OnMemoryPressure();
}
const auto& child = mNotLost->outOfProcess->mWebGLChild;
const auto& child = mNotLost->outOfProcess;
(void)child->SendOnMemoryPressure();
}
@ -933,7 +884,7 @@ RefPtr<gfx::SourceSurface> ClientWebGLContext::GetFrontBufferSnapshot(
}
return surf;
}
const auto& child = mNotLost->outOfProcess->mWebGLChild;
const auto& child = mNotLost->outOfProcess;
child->FlushPendingCmds();
webgl::FrontBufferSnapshotIpc res;
if (!child->SendGetFrontBufferSnapshot(&res)) {
@ -1137,7 +1088,7 @@ ClientWebGLContext::CreateOpaqueFramebuffer(
}
return ret.forget();
}
const auto& child = mNotLost->outOfProcess->mWebGLChild;
const auto& child = mNotLost->outOfProcess;
child->FlushPendingCmds();
bool ok = false;
if (!child->SendCreateOpaqueFramebuffer(ret->mId, options, &ok))
@ -1669,7 +1620,7 @@ bool ClientWebGLContext::IsEnabled(GLenum cap) const {
if (inProcess) {
return inProcess->IsEnabled(cap);
}
const auto& child = notLost->outOfProcess->mWebGLChild;
const auto& child = notLost->outOfProcess;
child->FlushPendingCmds();
bool ret = {};
if (!child->SendIsEnabled(cap, &ret)) return false;
@ -1691,7 +1642,7 @@ void ClientWebGLContext::GetInternalformatParameter(
maybe = inProcessContext->GetInternalformatParameter(target, internalformat,
pname);
} else {
const auto& child = notLost->outOfProcess->mWebGLChild;
const auto& child = notLost->outOfProcess;
child->FlushPendingCmds();
if (!child->SendGetInternalformatParameter(target, internalformat, pname,
&maybe)) {
@ -1757,7 +1708,7 @@ Maybe<double> ClientWebGLContext::GetNumber(const GLenum pname) {
return inProcess->GetNumber(pname);
}
const auto& child = mNotLost->outOfProcess->mWebGLChild;
const auto& child = mNotLost->outOfProcess;
child->FlushPendingCmds();
Maybe<double> ret;
@ -1775,7 +1726,7 @@ Maybe<std::string> ClientWebGLContext::GetString(const GLenum pname) {
return inProcess->GetString(pname);
}
const auto& child = mNotLost->outOfProcess->mWebGLChild;
const auto& child = mNotLost->outOfProcess;
child->FlushPendingCmds();
Maybe<std::string> ret;
@ -2203,7 +2154,7 @@ void ClientWebGLContext::GetBufferParameter(
if (inProcess) {
return inProcess->GetBufferParameter(target, pname);
}
const auto& child = mNotLost->outOfProcess->mWebGLChild;
const auto& child = mNotLost->outOfProcess;
child->FlushPendingCmds();
Maybe<double> ret;
if (!child->SendGetBufferParameter(target, pname, &ret)) {
@ -2257,7 +2208,7 @@ void ClientWebGLContext::GetFramebufferAttachmentParameter(
return inProcess->GetFramebufferAttachmentParameter(fbId, attachment,
pname);
}
const auto& child = mNotLost->outOfProcess->mWebGLChild;
const auto& child = mNotLost->outOfProcess;
child->FlushPendingCmds();
Maybe<double> ret;
if (!child->SendGetFramebufferAttachmentParameter(fbId, attachment, pname,
@ -2332,7 +2283,7 @@ void ClientWebGLContext::GetRenderbufferParameter(
if (inProcess) {
return inProcess->GetRenderbufferParameter(rbId, pname);
}
const auto& child = mNotLost->outOfProcess->mWebGLChild;
const auto& child = mNotLost->outOfProcess;
child->FlushPendingCmds();
Maybe<double> ret;
if (!child->SendGetRenderbufferParameter(rbId, pname, &ret)) {
@ -2384,7 +2335,7 @@ void ClientWebGLContext::GetIndexedParameter(
if (inProcess) {
return inProcess->GetIndexedParameter(target, index);
}
const auto& child = mNotLost->outOfProcess->mWebGLChild;
const auto& child = mNotLost->outOfProcess;
child->FlushPendingCmds();
Maybe<double> ret;
if (!child->SendGetIndexedParameter(target, index, &ret)) {
@ -2424,7 +2375,7 @@ void ClientWebGLContext::GetUniform(JSContext* const cx,
if (inProcess) {
return inProcess->GetUniform(prog.mId, loc.mLocation);
}
const auto& child = mNotLost->outOfProcess->mWebGLChild;
const auto& child = mNotLost->outOfProcess;
child->FlushPendingCmds();
webgl::GetUniformData ret;
if (!child->SendGetUniform(prog.mId, loc.mLocation, &ret)) {
@ -2540,7 +2491,7 @@ ClientWebGLContext::GetShaderPrecisionFormat(const GLenum shadertype,
if (inProcess) {
return inProcess->GetShaderPrecisionFormat(shadertype, precisiontype);
}
const auto& child = mNotLost->outOfProcess->mWebGLChild;
const auto& child = mNotLost->outOfProcess;
child->FlushPendingCmds();
Maybe<webgl::ShaderPrecisionFormat> ret;
if (!child->SendGetShaderPrecisionFormat(shadertype, precisiontype, &ret)) {
@ -2585,7 +2536,7 @@ GLenum ClientWebGLContext::CheckFramebufferStatus(GLenum target) {
if (inProcess) {
return inProcess->CheckFramebufferStatus(target);
}
const auto& child = mNotLost->outOfProcess->mWebGLChild;
const auto& child = mNotLost->outOfProcess;
child->FlushPendingCmds();
GLenum ret = 0;
if (!child->SendCheckFramebufferStatus(target, &ret)) {
@ -2711,7 +2662,7 @@ void ClientWebGLContext::Flush() {
Run<RPROC(Flush)>();
if (notLost->inProcess) return;
const auto& child = mNotLost->outOfProcess->mWebGLChild;
const auto& child = mNotLost->outOfProcess;
child->FlushPendingCmds();
}
@ -2723,7 +2674,7 @@ void ClientWebGLContext::Finish() {
inProcess->Finish();
return;
}
const auto& child = mNotLost->outOfProcess->mWebGLChild;
const auto& child = mNotLost->outOfProcess;
child->FlushPendingCmds();
(void)child->SendFinish();
}
@ -2743,7 +2694,7 @@ GLenum ClientWebGLContext::GetError() {
if (inProcess) {
return inProcess->GetError();
}
const auto& child = notLost->outOfProcess->mWebGLChild;
const auto& child = notLost->outOfProcess;
child->FlushPendingCmds();
GLenum ret = 0;
if (!child->SendGetError(&ret)) {
@ -3116,7 +3067,7 @@ void ClientWebGLContext::GetBufferSubData(GLenum target, GLintptr srcByteOffset,
return;
}
const auto& child = notLost->outOfProcess->mWebGLChild;
const auto& child = notLost->outOfProcess;
child->FlushPendingCmds();
mozilla::ipc::Shmem rawShmem;
if (!child->SendGetBufferSubData(target, srcByteOffset, destView.length(),
@ -3688,7 +3639,7 @@ void ClientWebGLContext::GetTexParameter(
if (inProcess) {
return inProcess->GetTexParameter(tex->mId, pname);
}
const auto& child = mNotLost->outOfProcess->mWebGLChild;
const auto& child = mNotLost->outOfProcess;
child->FlushPendingCmds();
Maybe<double> ret;
if (!child->SendGetTexParameter(tex->mId, pname, &ret)) {
@ -4198,7 +4149,7 @@ void ClientWebGLContext::ValidateProgram(WebGLProgramJS& prog) const {
if (inProcess) {
return inProcess->ValidateProgram(prog.mId);
}
const auto& child = mNotLost->outOfProcess->mWebGLChild;
const auto& child = mNotLost->outOfProcess;
child->FlushPendingCmds();
bool ret = {};
if (!child->SendValidateProgram(prog.mId, &ret)) {
@ -4216,7 +4167,7 @@ Maybe<double> ClientWebGLContext::GetVertexAttribPriv(const GLuint index,
if (inProcess) {
return inProcess->GetVertexAttrib(index, pname);
}
const auto& child = mNotLost->outOfProcess->mWebGLChild;
const auto& child = mNotLost->outOfProcess;
child->FlushPendingCmds();
Maybe<double> ret;
if (!child->SendGetVertexAttrib(index, pname, &ret)) {
@ -4613,7 +4564,7 @@ void ClientWebGLContext::DoReadPixels(const webgl::ReadPixelsDesc& desc,
inProcess->ReadPixelsInto(desc, dest);
return;
}
const auto& child = notLost->outOfProcess->mWebGLChild;
const auto& child = notLost->outOfProcess;
child->FlushPendingCmds();
webgl::ReadPixelsResultIpc res = {};
if (!child->SendReadPixels(desc, dest.length(), &res)) {
@ -4738,7 +4689,7 @@ void ClientWebGLContext::GetQueryParameter(
if (inProcess) {
return inProcess->GetQueryParameter(query.mId, pname);
}
const auto& child = mNotLost->outOfProcess->mWebGLChild;
const auto& child = mNotLost->outOfProcess;
child->FlushPendingCmds();
Maybe<double> ret;
if (!child->SendGetQueryParameter(query.mId, pname, &ret)) {
@ -4871,7 +4822,7 @@ void ClientWebGLContext::GetSamplerParameter(
if (inProcess) {
return inProcess->GetSamplerParameter(sampler.mId, pname);
}
const auto& child = mNotLost->outOfProcess->mWebGLChild;
const auto& child = mNotLost->outOfProcess;
child->FlushPendingCmds();
Maybe<double> ret;
if (!child->SendGetSamplerParameter(sampler.mId, pname, &ret)) {
@ -4977,7 +4928,7 @@ GLenum ClientWebGLContext::ClientWaitSync(WebGLSyncJS& sync,
if (inProcess) {
return inProcess->ClientWaitSync(sync.mId, flags, timeout);
}
const auto& child = mNotLost->outOfProcess->mWebGLChild;
const auto& child = mNotLost->outOfProcess;
child->FlushPendingCmds();
GLenum ret = {};
if (!child->SendClientWaitSync(sync.mId, flags, timeout, &ret)) {
@ -5672,7 +5623,7 @@ GLint ClientWebGLContext::GetFragDataLocation(const WebGLProgramJS& prog,
if (inProcess) {
return inProcess->GetFragDataLocation(prog.mId, nameU8);
}
const auto& child = mNotLost->outOfProcess->mWebGLChild;
const auto& child = mNotLost->outOfProcess;
child->FlushPendingCmds();
GLint ret = {};
if (!child->SendGetFragDataLocation(prog.mId, nameU8, &ret)) {
@ -6019,7 +5970,7 @@ const webgl::CompileResult& ClientWebGLContext::GetCompileResult(
if (inProcess) {
return inProcess->GetCompileResult(shader.mId);
}
const auto& child = mNotLost->outOfProcess->mWebGLChild;
const auto& child = mNotLost->outOfProcess;
child->FlushPendingCmds();
webgl::CompileResult ret = {};
if (!child->SendGetCompileResult(shader.mId, &ret)) {
@ -6043,7 +5994,7 @@ const webgl::LinkResult& ClientWebGLContext::GetLinkResult(
if (inProcess) {
return inProcess->GetLinkResult(prog.mId);
}
const auto& child = mNotLost->outOfProcess->mWebGLChild;
const auto& child = mNotLost->outOfProcess;
child->FlushPendingCmds();
webgl::LinkResult ret;
if (!child->SendGetLinkResult(prog.mId, &ret)) {

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

@ -20,7 +20,6 @@
#include "WebGLTypes.h"
#include "mozilla/Logging.h"
#include "WebGLCrossProcessCommandQueue.h"
#include "WebGLCommandQueue.h"
#include <memory>
@ -28,19 +27,10 @@
#include <unordered_set>
#include <vector>
#ifndef WEBGL_BRIDGE_LOG_
# define WEBGL_BRIDGE_LOG_(lvl, ...) \
MOZ_LOG(mozilla::gWebGLBridgeLog, lvl, (__VA_ARGS__))
# define WEBGL_BRIDGE_LOGV(...) \
WEBGL_BRIDGE_LOG_(LogLevel::Verbose, __VA_ARGS__)
# define WEBGL_BRIDGE_LOGD(...) WEBGL_BRIDGE_LOG_(LogLevel::Debug, __VA_ARGS__)
# define WEBGL_BRIDGE_LOGI(...) WEBGL_BRIDGE_LOG_(LogLevel::Info, __VA_ARGS__)
# define WEBGL_BRIDGE_LOGE(...) WEBGL_BRIDGE_LOG_(LogLevel::Error, __VA_ARGS__)
#endif // WEBGL_BRIDGE_LOG_
namespace mozilla {
class ClientWebGLExtensionBase;
class HostWebGLContext;
namespace dom {
class WebGLChild;
@ -186,24 +176,19 @@ class ContextGenerationInfo final {
// -
struct RemotingData final {
// In the cross process case, the WebGL actor's ownership relationship looks
// like this:
// ---------------------------------------------------------------------
// | ClientWebGLContext -> WebGLChild -> WebGLParent -> HostWebGLContext
// ---------------------------------------------------------------------
//
// where 'A -> B' means "A owns B"
RefPtr<mozilla::dom::WebGLChild> mWebGLChild;
UniquePtr<ClientWebGLCommandSourceP> mCommandSourcePcq;
UniquePtr<ClientWebGLCommandSourceI> mCommandSourceIpdl;
};
// In the cross process case, the WebGL actor's ownership relationship looks
// like this:
// ---------------------------------------------------------------------
// | ClientWebGLContext -> WebGLChild -> WebGLParent -> HostWebGLContext
// ---------------------------------------------------------------------
//
// where 'A -> B' means "A owns B"
struct NotLostData final {
ClientWebGLContext& context;
webgl::InitContextResult info;
Maybe<RemotingData> outOfProcess;
RefPtr<mozilla::dom::WebGLChild> outOfProcess;
UniquePtr<HostWebGLContext> inProcess;
webgl::ContextGenerationInfo state;
@ -793,7 +778,7 @@ class ClientWebGLContext final : public nsICanvasRenderingContextInternal,
mozilla::dom::WebGLChild* GetChild() const {
if (!mNotLost) return nullptr;
if (!mNotLost->outOfProcess) return nullptr;
return mNotLost->outOfProcess->mWebGLChild.get();
return mNotLost->outOfProcess.get();
}
// -------------------------------------------------------------------------

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

@ -14,7 +14,6 @@
#include "WebGL2Context.h"
#include "WebGLBuffer.h"
#include "WebGLContext.h"
#include "WebGLCrossProcessCommandQueue.h"
#include "WebGLFramebuffer.h"
#include "WebGLMemoryTracker.h"
#include "WebGLParent.h"
@ -32,8 +31,6 @@
namespace mozilla {
LazyLogModule gWebGLBridgeLog("webglbridge");
// -
static StaticMutex sContextSetLock;
@ -56,30 +53,19 @@ LockedOutstandingContexts::~LockedOutstandingContexts() {
/*static*/
UniquePtr<HostWebGLContext> HostWebGLContext::Create(
OwnerData&& ownerData, const webgl::InitContextDesc& desc,
const OwnerData& ownerData, const webgl::InitContextDesc& desc,
webgl::InitContextResult* const out) {
auto host = WrapUnique(new HostWebGLContext(std::move(ownerData)));
auto host = WrapUnique(new HostWebGLContext(ownerData));
auto webgl = WebGLContext::Create(*host, desc, out);
if (!webgl) return nullptr;
return host;
}
HostWebGLContext::HostWebGLContext(OwnerData&& ownerData)
: mOwnerData(std::move(ownerData)) {
if (mOwnerData.outOfProcess) {
if (mOwnerData.outOfProcess->mCommandSinkP) {
mOwnerData.outOfProcess->mCommandSinkP->mHostContext = this;
}
if (mOwnerData.outOfProcess->mCommandSinkI) {
mOwnerData.outOfProcess->mCommandSinkI->mHostContext = this;
}
}
{
StaticMutexAutoLock lock(sContextSetLock);
auto& contexts = DeferredStaticContextSet();
(void)contexts.insert(this);
}
HostWebGLContext::HostWebGLContext(const OwnerData& ownerData)
: mOwnerData(ownerData) {
StaticMutexAutoLock lock(sContextSetLock);
auto& contexts = DeferredStaticContextSet();
(void)contexts.insert(this);
}
HostWebGLContext::~HostWebGLContext() {
@ -92,18 +78,18 @@ HostWebGLContext::~HostWebGLContext() {
void HostWebGLContext::OnContextLoss(const webgl::ContextLossReason reason) {
if (mOwnerData.inProcess) {
(*mOwnerData.inProcess)->OnContextLoss(reason);
mOwnerData.inProcess->OnContextLoss(reason);
} else {
(void)mOwnerData.outOfProcess->mParent.SendOnContextLoss(reason);
(void)mOwnerData.outOfProcess->SendOnContextLoss(reason);
}
}
void HostWebGLContext::JsWarning(const std::string& text) const {
if (mOwnerData.inProcess) {
(*mOwnerData.inProcess)->JsWarning(text);
mOwnerData.inProcess->JsWarning(text);
return;
}
(void)mOwnerData.outOfProcess->mParent.SendJsWarning(text);
(void)mOwnerData.outOfProcess->SendJsWarning(text);
}
Maybe<layers::SurfaceDescriptor> HostWebGLContext::GetFrontBuffer(

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

@ -17,25 +17,14 @@
#include "WebGLFramebuffer.h"
#include "WebGLTypes.h"
#include "WebGLCommandQueue.h"
#include "WebGLCrossProcessCommandQueue.h"
#include "ProducerConsumerQueue.h"
#include "IpdlQueue.h"
#include <unordered_map>
#include <unordered_set>
#include <vector>
#ifndef WEBGL_BRIDGE_LOG_
# define WEBGL_BRIDGE_LOG_(lvl, ...) \
MOZ_LOG(mozilla::gWebGLBridgeLog, lvl, (__VA_ARGS__))
# define WEBGL_BRIDGE_LOGD(...) WEBGL_BRIDGE_LOG_(LogLevel::Debug, __VA_ARGS__)
# define WEBGL_BRIDGE_LOGE(...) WEBGL_BRIDGE_LOG_(LogLevel::Error, __VA_ARGS__)
#endif // WEBGL_BRIDGE_LOG_
namespace mozilla {
extern LazyLogModule gWebGLBridgeLog;
namespace dom {
class WebGLParent;
}
@ -80,22 +69,17 @@ class HostWebGLContext final : public SupportsWeakPtr {
}
public:
struct RemotingData final {
dom::WebGLParent& mParent;
UniquePtr<HostWebGLCommandSinkP> mCommandSinkP;
UniquePtr<HostWebGLCommandSinkI> mCommandSinkI;
};
struct OwnerData final {
Maybe<ClientWebGLContext*> inProcess;
Maybe<RemotingData> outOfProcess;
ClientWebGLContext* inProcess = nullptr;
dom::WebGLParent* outOfProcess = nullptr;
};
static UniquePtr<HostWebGLContext> Create(OwnerData&&,
static UniquePtr<HostWebGLContext> Create(const OwnerData&,
const webgl::InitContextDesc&,
webgl::InitContextResult* out);
private:
explicit HostWebGLContext(OwnerData&&);
explicit HostWebGLContext(const OwnerData&);
public:
virtual ~HostWebGLContext();
@ -794,9 +778,6 @@ class HostWebGLContext final : public SupportsWeakPtr {
MOZ_RELEASE_ASSERT(mContext->IsWebGL2(), "Requires WebGL2 context");
return static_cast<WebGL2Context*>(mContext.get());
}
// mozilla::ipc::Shmem PopShmem() { return mShmemStack.PopLastElement(); }
// nsTArray<mozilla::ipc::Shmem> mShmemStack;
};
} // namespace mozilla

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

@ -25,8 +25,6 @@ using mozilla::webgl::ShaderPrecisionFormat from "mozilla/dom/WebGLIpdl.h";
using mozilla::webgl::OpaqueFramebufferOptions from "mozilla/dom/WebGLIpdl.h";
using mozilla::webgl::ReadPixelsDesc from "mozilla/dom/WebGLIpdl.h";
using mozilla::webgl::ReadPixelsResultIpc from "mozilla/dom/WebGLIpdl.h";
using mozilla::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";
@ -43,8 +41,7 @@ sync refcounted protocol PWebGL
manager PCompositorBridge;
parent:
sync Initialize(InitContextDesc desc, UniquePtr<HostWebGLCommandSinkP> sinkP,
UniquePtr<HostWebGLCommandSinkI> sinkI)
sync Initialize(InitContextDesc desc)
returns (InitContextResult res);
async __delete__();

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

@ -1,989 +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 mozilla_ipc_ProducerConsumerQueue_h
#define mozilla_ipc_ProducerConsumerQueue_h 1
#include <atomic>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>
#include "mozilla/StaticPtr.h"
#include "mozilla/WeakPtr.h"
#include "mozilla/dom/QueueParamTraits.h"
#include "mozilla/ipc/ShmemMessageUtils.h"
#include "CrossProcessSemaphore.h"
#include "nsThreadUtils.h"
namespace IPC {
template <typename T>
struct ParamTraits;
} // namespace IPC
namespace mozilla {
namespace webgl {
using mozilla::ipc::IProtocol;
using mozilla::ipc::Shmem;
extern LazyLogModule gPCQLog;
#define PCQ_LOG_(lvl, ...) MOZ_LOG(mozilla::webgl::gPCQLog, lvl, (__VA_ARGS__))
#define PCQ_LOGD(...) PCQ_LOG_(LogLevel::Debug, __VA_ARGS__)
#define PCQ_LOGE(...) PCQ_LOG_(LogLevel::Error, __VA_ARGS__)
class ProducerConsumerQueue;
class PcqProducer;
class PcqConsumer;
/**
* PcqActor is an actor base-class that is used as a static map that
* provides casting from an IProtocol to a PcqActor. PcqActors delegate
* all needed IProtocol operations and also support weak references.
* Actors used to construct a PCQ must implement this class.
* Example:
* class MyActorParent : public PMyActorParent, public PcqActor {
* MyActorParent() : PcqActor(this) {}
* // ...
* }
* Implementations of abstract methods will typically just forward to IProtocol.
*/
class PcqActor : public SupportsWeakPtr {
// The IProtocol part of `this`.
IProtocol* mProtocol;
using PcqActorMap = std::unordered_map<IProtocol*, PcqActor*>;
// uses StaticAutoPtr to placate anti-static-ctor static analysis
inline static StaticAutoPtr<PcqActorMap> sMap;
static bool IsActorThread() {
static nsIThread* sActorThread = [] { return NS_GetCurrentThread(); }();
return sActorThread == NS_GetCurrentThread();
}
protected:
explicit PcqActor(IProtocol* aProtocol) : mProtocol(aProtocol) {
MOZ_ASSERT(IsActorThread());
if (!sMap) {
sMap = new PcqActorMap();
}
sMap->insert({mProtocol, this});
}
~PcqActor() {
MOZ_ASSERT(IsActorThread());
sMap->erase(mProtocol);
if (sMap->empty()) {
delete sMap;
sMap = nullptr;
}
}
public:
Shmem::SharedMemory* LookupSharedMemory(int32_t aId) {
return mProtocol->LookupSharedMemory(aId);
}
int32_t Id() const { return mProtocol->Id(); }
base::ProcessId OtherPid() const { return mProtocol->OtherPid(); }
bool AllocShmem(size_t aSize,
mozilla::ipc::SharedMemory::SharedMemoryType aShmType,
mozilla::ipc::Shmem* aShmem) {
return mProtocol->AllocShmem(aSize, aShmType, aShmem);
}
static PcqActor* LookupProtocol(IProtocol* aProtocol) {
MOZ_ASSERT(IsActorThread());
MOZ_ASSERT(sMap);
if (!sMap) {
return nullptr;
}
auto it = sMap->find(aProtocol);
return (it != sMap->end()) ? it->second : nullptr;
}
};
} // namespace webgl
// NB: detail is in mozilla instead of mozilla::webgl because many points in
// existing code get confused if mozilla::detail and mozilla::webgl::detail
// exist.
namespace detail {
using mozilla::ipc::IProtocol;
using mozilla::ipc::Shmem;
using mozilla::webgl::IsSuccess;
using mozilla::webgl::PcqActor;
using mozilla::webgl::ProducerConsumerQueue;
using mozilla::webgl::QueueStatus;
constexpr size_t GetCacheLineSize() { return 64; }
// NB: The header may end up consuming fewer bytes than this. This value
// guarantees that we can always byte-align the header contents.
constexpr size_t GetMaxHeaderSize() {
// Recall that the Shmem contents are laid out like this:
// -----------------------------------------------------------------------
// queue contents | align1 | mRead | align2 | mWrite | align3 | User Data
// -----------------------------------------------------------------------
constexpr size_t alignment =
std::max(std::alignment_of<size_t>::value, GetCacheLineSize());
static_assert(alignment >= sizeof(size_t),
"alignment expected to be large enough to hold a size_t");
// We may need up to this many bytes to properly align mRead
constexpr size_t maxAlign1 = alignment - 1;
constexpr size_t readAndAlign2 = alignment;
constexpr size_t writeAndAlign3 = alignment;
return maxAlign1 + readAndAlign2 + writeAndAlign3;
}
template <typename View, typename Arg, typename... Args>
size_t MinSizeofArgs(View& aView, const Arg& aArg, const Args&... aArgs) {
return aView.MinSizeParam(aArg) + MinSizeofArgs(aView, aArgs...);
}
template <typename View>
size_t MinSizeofArgs(View&) {
return 0;
}
class PcqRCSemaphore {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PcqRCSemaphore)
explicit PcqRCSemaphore(CrossProcessSemaphore* aSem) : mSem(aSem) {
MOZ_ASSERT(mSem);
}
bool Wait(const Maybe<TimeDuration>& aTime) { return mSem->Wait(aTime); }
void Signal() { mSem->Signal(); }
bool IsAvailable() {
MOZ_ASSERT_UNREACHABLE("Unimplemented");
return false;
}
CrossProcessSemaphoreHandle ShareToProcess(base::ProcessId aTargetPid) {
return mSem->ShareToProcess(aTargetPid);
}
void CloseHandle() { mSem->CloseHandle(); }
private:
~PcqRCSemaphore() { delete mSem; }
CrossProcessSemaphore* mSem;
};
/**
* Common base class for PcqProducer and Consumer.
*/
class PcqBase {
public:
/**
* Bytes used in the queue if the parameters are the read/write heads.
*/
size_t UsedBytes(size_t aRead, size_t aWrite) {
MOZ_ASSERT(ValidState(aRead, aWrite));
return mozilla::webgl::UsedBytes(QueueBufferSize(), aRead, aWrite);
}
/**
* Bytes free in the queue if the parameters are the read/write heads.
*/
size_t FreeBytes(size_t aRead, size_t aWrite) {
MOZ_ASSERT(ValidState(aRead, aWrite));
return mozilla::webgl::FreeBytes(QueueBufferSize(), aRead, aWrite);
}
/**
* True when this queue is valid with the parameters as the read/write heads.
*/
bool ValidState(size_t aRead, size_t aWrite) {
return (aRead < QueueBufferSize()) && (aWrite < QueueBufferSize());
}
/**
* True when this queue is empty with the parameters as the read/write heads.
*/
bool IsEmpty(size_t aRead, size_t aWrite) {
MOZ_ASSERT(ValidState(aRead, aWrite));
return UsedBytes(aRead, aWrite) == 0;
}
/**
* True when this queue is full with the parameters as the read/write heads.
*/
bool IsFull(size_t aRead, size_t aWrite) {
MOZ_ASSERT(ValidState(aRead, aWrite));
return FreeBytes(aRead, aWrite) == 0;
}
// Cheaply get the used size of the current queue. This does no
// synchronization so the information may be stale. On the PcqProducer
// side, it will never underestimate the number of bytes used and,
// on the Consumer side, it will never overestimate them.
// (The reciprocal is true of FreeBytes.)
size_t UsedBytes() {
size_t write = mWrite->load(std::memory_order_relaxed);
size_t read = mRead->load(std::memory_order_relaxed);
return UsedBytes(read, write);
}
// This does no synchronization so the information may be stale.
size_t FreeBytes() { return QueueSize() - UsedBytes(); }
// This does no synchronization so the information may be stale.
bool IsEmpty() { return IsEmpty(GetReadRelaxed(), GetWriteRelaxed()); }
// This does no synchronization so the information may be stale.
bool IsFull() { return IsFull(GetReadRelaxed(), GetWriteRelaxed()); }
protected:
friend struct mozilla::ipc::IPDLParamTraits<PcqBase>;
friend ProducerConsumerQueue;
PcqBase() = default;
PcqBase(Shmem& aShmem, IProtocol* aProtocol, size_t aQueueSize,
RefPtr<PcqRCSemaphore> aMaybeNotEmptySem,
RefPtr<PcqRCSemaphore> aMaybeNotFullSem) {
Set(aShmem, aProtocol, aQueueSize, aMaybeNotEmptySem, aMaybeNotFullSem);
}
PcqBase(const PcqBase&) = delete;
PcqBase(PcqBase&&) = default;
PcqBase& operator=(const PcqBase&) = delete;
PcqBase& operator=(PcqBase&&) = default;
void Set(Shmem& aShmem, IProtocol* aProtocol, size_t aQueueSize,
RefPtr<PcqRCSemaphore> aMaybeNotEmptySem,
RefPtr<PcqRCSemaphore> aMaybeNotFullSem) {
mActor = PcqActor::LookupProtocol(aProtocol);
MOZ_RELEASE_ASSERT(mActor);
mOtherPid = mActor->OtherPid();
mShmem = aShmem;
mQueue = aShmem.get<uint8_t>();
// NB: The buffer needs one extra byte for the queue contents
mQueueBufferSize = aQueueSize + 1;
// Recall that the Shmem contents are laid out like this:
// -----------------------------------------------------------------------
// queue contents | align1 | mRead | align2 | mWrite | align3 | User Data
// -----------------------------------------------------------------------
size_t shmemSize = aShmem.Size<uint8_t>();
uint8_t* header = mQueue + mQueueBufferSize;
constexpr size_t alignment =
std::max(std::alignment_of<size_t>::value, GetCacheLineSize());
static_assert(alignment >= sizeof(size_t),
"alignment expected to be large enough to hold a size_t");
static_assert((alignment & (alignment - 1)) == 0,
"alignment must be a power of 2");
// We may need up to this many bytes to properly align mRead
constexpr size_t maxAlign1 = alignment - 1;
// Find the lowest value of align1 that assures proper byte-alignment.
uintptr_t alignValue = reinterpret_cast<uintptr_t>(header + maxAlign1);
alignValue &= ~(alignment - 1);
uint8_t* metadata = reinterpret_cast<uint8_t*>(alignValue);
// NB: We do not call the nontrivial constructor here (we do not write
// `new std::atomic_size_t()`) because it would zero the read/write values
// in the shared memory, which may already represent data in the queue.
mRead = new (metadata) std::atomic_size_t;
mWrite = new (metadata + alignment) std::atomic_size_t;
// The actual number of bytes we needed to properly align mRead
size_t align1 = metadata - header;
MOZ_ASSERT(align1 <= maxAlign1);
// The rest of the memory is the user reserved memory
size_t headerSize = align1 + 2 * alignment;
size_t userSize = shmemSize - mQueueBufferSize - headerSize;
if (userSize > 0) {
mUserReservedMemory = mQueue + mQueueBufferSize + headerSize;
mUserReservedSize = userSize;
} else {
mUserReservedMemory = nullptr;
mUserReservedSize = 0;
}
// We use Monitors to wait for data when reading from an empty queue
// and to wait for free space when writing to a full one.
MOZ_ASSERT(aMaybeNotEmptySem && aMaybeNotFullSem);
mMaybeNotEmptySem = aMaybeNotEmptySem;
mMaybeNotFullSem = aMaybeNotFullSem;
PCQ_LOGD("Created queue (%p) with size: %zu, alignment: %zu, align1: %zu",
this, aQueueSize, alignment, align1);
}
~PcqBase() {
PCQ_LOGD("Destroying queue (%p).", this);
// NB: We would call the destructors for mRead and mWrite here (but not
// delete since their memory belongs to the shmem) but the std library's
// type aliases make this tricky and, by the spec for std::atomic, their
// destructors are trivial (i.e. no-ops) anyway.
}
size_t GetReadRelaxed() { return mRead->load(std::memory_order_relaxed); }
size_t GetWriteRelaxed() { return mWrite->load(std::memory_order_relaxed); }
/**
* The QueueSize is the number of bytes the queue can hold. The queue is
* backed by a buffer that is one byte larger than this, meaning that one
* byte of the buffer is always wasted.
* This is usually the right method to use when testing queue capacity.
*/
size_t QueueSize() { return QueueBufferSize() - 1; }
/**
* The QueueBufferSize is the number of bytes in the buffer that the queue
* uses for storage.
* This is usually the right method to use when calculating read/write head
* positions.
*/
size_t QueueBufferSize() { return mQueueBufferSize; }
// Actor used for making Shmems.
WeakPtr<PcqActor> mActor;
// PID of process on the other end. Both ends may run on the same process.
base::ProcessId mOtherPid = 0;
uint8_t* mQueue = nullptr;
size_t mQueueBufferSize = 0;
// Pointer to memory reserved for use by the user, or null if none
uint8_t* mUserReservedMemory = nullptr;
size_t mUserReservedSize = 0;
// These std::atomics are in shared memory so DO NOT DELETE THEM! We should,
// however, call their destructors.
std::atomic_size_t* mRead = nullptr;
std::atomic_size_t* mWrite = nullptr;
// The Shmem contents are laid out like this:
// -----------------------------------------------------------------------
// queue contents | align1 | mRead | align2 | mWrite | align3 | User Data
// -----------------------------------------------------------------------
// where align1 is chosen so that mRead is properly aligned for a
// std_atomic_size_t and is on a cache line separate from the queue contents
// align2 and align3 is chosen to separate mRead/mWrite and mWrite/User Data
// similarly.
Shmem mShmem;
// Two semaphores that are signaled when the queue goes from a state
// where it definitely is empty/full to a state where it "may not be".
// Therefore, we can wait on them and know that we will be awakened if
// there may be work to do.
// Our use of these semaphores leans heavily on the assumption that
// the queue is used by one producer and one consumer.
RefPtr<PcqRCSemaphore> mMaybeNotEmptySem;
RefPtr<PcqRCSemaphore> mMaybeNotFullSem;
};
} // namespace detail
namespace webgl {
using mozilla::ipc::Shmem;
/**
* The PcqProducer is the endpoint that inserts elements into the queue. It
* should only be used from one thread at a time.
*/
class PcqProducer : public detail::PcqBase {
public:
PcqProducer(PcqProducer&& aOther) = default;
PcqProducer& operator=(PcqProducer&&) = default;
PcqProducer() = default; // for IPDL
/**
* The number of bytes that the queue can hold.
*/
size_t Size() { return QueueSize(); }
/**
* Attempts to insert aArgs into the queue. If the operation does not
* succeed then the queue is unchanged.
*/
template <typename... Args>
QueueStatus TryInsert(Args&&... aArgs) {
size_t write = mWrite->load(std::memory_order_relaxed);
const size_t initWrite = write;
size_t read = mRead->load(std::memory_order_acquire);
if (!ValidState(read, write)) {
PCQ_LOGE(
"Queue was found in an invalid state. Queue Size: %zu. "
"Read: %zu. Write: %zu",
Size(), read, write);
return QueueStatus::kFatalError;
}
ProducerView view(this, read, &write);
// Check that the queue has enough unoccupied room for all Args types.
// This is based on the user's size estimate for args from QueueParamTraits.
size_t bytesNeeded = detail::MinSizeofArgs(view, aArgs...);
if (Size() < bytesNeeded) {
PCQ_LOGE(
"Queue is too small for objects. Queue Size: %zu. "
"Needed: %zu",
Size(), bytesNeeded);
return QueueStatus::kTooSmall;
}
if (FreeBytes(read, write) < bytesNeeded) {
PCQ_LOGD(
"Not enough room to insert. Has: %zu (%zu,%zu). "
"Needed: %zu",
FreeBytes(read, write), read, write, bytesNeeded);
return QueueStatus::kNotReady;
}
// Try to insert args in sequence. Only update the queue if the
// operation was successful. We already checked all normal means of
// failure but we can expect occasional failure here if the user's
// QueueParamTraits::MinSize method was inexact.
QueueStatus status = TryInsertHelper(view, aArgs...);
if (!status) {
PCQ_LOGD(
"Failed to insert with error (%d). Has: %zu (%zu,%zu). "
"Estimate of bytes needed: %zu",
(int)status, FreeBytes(read, write), read, write, bytesNeeded);
return status;
}
MOZ_ASSERT(ValidState(read, write));
// Check that at least bytesNeeded were produced. Failing this means
// that some QueueParamTraits::MinSize estimated too many bytes.
bool enoughBytes =
UsedBytes(read, write) >=
UsedBytes(read, (initWrite + bytesNeeded) % QueueBufferSize());
MOZ_ASSERT(enoughBytes);
if (!enoughBytes) {
return QueueStatus::kFatalError;
}
// Commit the transaction.
PCQ_LOGD(
"Successfully inserted. PcqProducer used %zu bytes total. "
"Write index: %zu -> %zu",
bytesNeeded, initWrite, write);
mWrite->store(write, std::memory_order_release);
// Set the semaphore (unless it is already set) to let the consumer know
// that the queue may not be empty. We just need to guarantee that it
// was set (i.e. non-zero) at some time after mWrite was updated.
if (!mMaybeNotEmptySem->IsAvailable()) {
mMaybeNotEmptySem->Signal();
}
return status;
}
/**
* Attempts to insert aArgs into the queue. If the operation does not
* succeed in the time allotted then the queue is unchanged.
*/
template <typename... Args>
QueueStatus TryWaitInsert(const Maybe<TimeDuration>& aDuration,
Args&&... aArgs) {
return TryWaitInsertImpl(false, aDuration, std::forward<Args>(aArgs)...);
}
QueueStatus AllocShmem(mozilla::ipc::Shmem* aShmem, size_t aBufferSize,
const void* aBuffer = nullptr) {
if (!mActor) {
return QueueStatus::kFatalError;
}
if (!mActor->AllocShmem(
aBufferSize,
mozilla::ipc::SharedMemory::SharedMemoryType::TYPE_BASIC, aShmem)) {
return QueueStatus::kOOMError;
}
if (aBuffer) {
memcpy(aShmem->get<uint8_t>(), aBuffer, aBufferSize);
}
return QueueStatus::kSuccess;
}
protected:
friend ProducerConsumerQueue;
friend ProducerView<PcqProducer>;
template <typename Arg, typename... Args>
QueueStatus TryInsertHelper(ProducerView<PcqProducer>& aView, Arg&& aArg,
Args&&... aArgs) {
QueueStatus status = TryInsertItem(aView, std::forward<Arg>(aArg));
return IsSuccess(status) ? TryInsertHelper(aView, aArgs...) : status;
}
QueueStatus TryInsertHelper(ProducerView<PcqProducer>&) {
return QueueStatus::kSuccess;
}
template <typename Arg>
QueueStatus TryInsertItem(ProducerView<PcqProducer>& aView, Arg&& aArg) {
return QueueParamTraits<typename RemoveCVR<Arg>::Type>::Write(
aView, std::forward<Arg>(aArg));
}
template <typename... Args>
QueueStatus TryWaitInsertImpl(bool aRecursed,
const Maybe<TimeDuration>& aDuration,
Args&&... aArgs) {
// Wait up to aDuration for the not-full semaphore to be signaled.
// If we run out of time then quit.
TimeStamp start(TimeStamp::Now());
if (aRecursed && (!mMaybeNotFullSem->Wait(aDuration))) {
return QueueStatus::kNotReady;
}
// Attempt to insert all args. No waiting is done here.
QueueStatus status = TryInsert(std::forward<Args>(aArgs)...);
TimeStamp now;
if (aRecursed && IsSuccess(status)) {
// If our local view of the queue is that it is still not full then
// we know it won't get full without us (we are the only producer).
// So re-set the not-full semaphore unless it's already set.
// (We are also the only not-full semaphore decrementer so it can't
// become 0.)
if ((!IsFull()) && (!mMaybeNotFullSem->IsAvailable())) {
mMaybeNotFullSem->Signal();
}
} else if ((status == QueueStatus::kNotReady) &&
(aDuration.isNothing() ||
((now = TimeStamp::Now()) - start) < aDuration.value())) {
// We don't have enough room but still have time, e.g. because
// the consumer read some data but not enough or because the
// not-full semaphore gave a false positive. Either way, retry.
status =
aDuration.isNothing()
? TryWaitInsertImpl(true, aDuration, std::forward<Args>(aArgs)...)
: TryWaitInsertImpl(true, Some(aDuration.value() - (now - start)),
std::forward<Args>(aArgs)...);
}
return status;
}
template <typename Arg>
QueueStatus WriteObject(size_t aRead, size_t* aWrite, const Arg& arg,
size_t aArgSize) {
return Marshaller::WriteObject(mQueue, QueueBufferSize(), aRead, aWrite,
arg, aArgSize);
}
// Currently, the PCQ requires any parameters expected to need more than
// 1/16 the total number of bytes in the command queue to use their own
// SharedMemory.
bool NeedsSharedMemory(size_t aRequested) {
return (Size() / 16) < aRequested;
}
PcqProducer(Shmem& aShmem, IProtocol* aProtocol, size_t aQueueSize,
RefPtr<detail::PcqRCSemaphore> aMaybeNotEmptySem,
RefPtr<detail::PcqRCSemaphore> aMaybeNotFullSem)
: PcqBase(aShmem, aProtocol, aQueueSize, aMaybeNotEmptySem,
aMaybeNotFullSem) {
// Since they are shared, this initializes mRead/mWrite in the PcqConsumer
// as well.
*mRead = 0;
*mWrite = 0;
}
PcqProducer(const PcqProducer&) = delete;
PcqProducer& operator=(const PcqProducer&) = delete;
};
class PcqConsumer : public detail::PcqBase {
public:
PcqConsumer(PcqConsumer&& aOther) = default;
PcqConsumer& operator=(PcqConsumer&&) = default;
PcqConsumer() = default; // for IPDL
/**
* The number of bytes that the queue can hold.
*/
size_t Size() { return QueueSize(); }
/**
* Attempts to copy and remove aArgs from the queue. If the operation does
* not succeed then the queue is unchanged.
*/
template <typename... Args>
QueueStatus TryRemove(Args&... aArgs) {
return TryRemoveImpl(aArgs...);
}
/**
* Wait for up to aDuration to remove the requested data from the queue.
* Pass Nothing to wait until removal succeeds.
*/
template <typename... Args>
QueueStatus TryWaitRemove(const Maybe<TimeDuration>& aDuration,
Args&... aArgs) {
return TryWaitRemoveImpl(false, aDuration, aArgs...);
}
mozilla::ipc::Shmem::SharedMemory* LookupSharedMemory(uint32_t aId) {
if (!mActor) {
return nullptr;
}
return mActor->LookupSharedMemory(aId);
}
protected:
friend ProducerConsumerQueue;
friend ConsumerView<PcqConsumer>;
template <typename... Args>
QueueStatus TryRemoveImpl(Args&... aArgs) {
size_t write = mWrite->load(std::memory_order_acquire);
size_t read = mRead->load(std::memory_order_relaxed);
const size_t initRead = read;
if (!ValidState(read, write)) {
PCQ_LOGE(
"Queue was found in an invalid state. Queue Size: %zu. "
"Read: %zu. Write: %zu",
Size(), read, write);
return QueueStatus::kFatalError;
}
ConsumerView<PcqConsumer> view(this, &read, write);
// Check that the queue has enough unoccupied room for all Args types.
// This is based on the user's size estimate for Args from QueueParamTraits.
size_t bytesNeeded = detail::MinSizeofArgs(view, aArgs...);
if (Size() < bytesNeeded) {
PCQ_LOGE(
"Queue is too small for objects. Queue Size: %zu. "
"Bytes needed: %zu.",
Size(), bytesNeeded);
return QueueStatus::kTooSmall;
}
if (UsedBytes(read, write) < bytesNeeded) {
PCQ_LOGD(
"Not enough data in queue. Has: %zu (%zu,%zu). "
"Bytes needed: %zu",
UsedBytes(read, write), read, write, bytesNeeded);
return QueueStatus::kNotReady;
}
// Only update the queue if the operation was successful.
QueueStatus status = TryRemoveArgs(view, aArgs...);
if (!status) {
return status;
}
// Check that at least bytesNeeded were consumed. Failing this means
// that some QueueParamTraits::MinSize estimated too many bytes.
bool enoughBytes =
FreeBytes(read, write) >=
FreeBytes((initRead + bytesNeeded) % QueueBufferSize(), write);
MOZ_ASSERT(enoughBytes);
if (!enoughBytes) {
return QueueStatus::kFatalError;
}
MOZ_ASSERT(ValidState(read, write));
PCQ_LOGD(
"Successfully removed. PcqConsumer used %zu bytes total. "
"Read index: %zu -> %zu",
bytesNeeded, initRead, read);
// Commit the transaction.
mRead->store(read, std::memory_order_release);
// Set the semaphore (unless it is already set) to let the producer know
// that the queue may not be full. We just need to guarantee that it
// was set (i.e. non-zero) at some time after mRead was updated.
if (!mMaybeNotFullSem->IsAvailable()) {
mMaybeNotFullSem->Signal();
}
return status;
}
template <typename... Args>
QueueStatus TryWaitRemoveImpl(bool aRecursed,
const Maybe<TimeDuration>& aDuration,
Args&... aArgs) {
// Wait up to aDuration for the not-empty semaphore to be signaled.
// If we run out of time then quit.
TimeStamp start(TimeStamp::Now());
if (aRecursed && (!mMaybeNotEmptySem->Wait(aDuration))) {
return QueueStatus::kNotReady;
}
// Attempt to read all args. No waiting is done here.
QueueStatus status = TryRemove(aArgs...);
TimeStamp now;
if (aRecursed && IsSuccess(status)) {
// If our local view of the queue is that it is still not empty then
// we know it won't get empty without us (we are the only consumer).
// So re-set the not-empty semaphore unless it's already set.
// (We are also the only not-empty semaphore decrementer so it can't
// become 0.)
if ((!IsEmpty()) && (!mMaybeNotEmptySem->IsAvailable())) {
mMaybeNotEmptySem->Signal();
}
} else if ((status == QueueStatus::kNotReady) &&
(aDuration.isNothing() ||
((now = TimeStamp::Now()) - start) < aDuration.value())) {
// We don't have enough data but still have time, e.g. because
// the producer wrote some data but not enough or because the
// not-empty semaphore gave a false positive. Either way, retry.
status =
aDuration.isNothing()
? TryWaitRemoveImpl(true, aDuration, aArgs...)
: TryWaitRemoveImpl(true, Some(aDuration.value() - (now - start)),
aArgs...);
}
return status;
}
// Version of the helper for copying values out of the queue.
template <typename... Args>
QueueStatus TryRemoveArgs(ConsumerView<PcqConsumer>& aView, Args&... aArgs);
template <typename Arg, typename... Args>
QueueStatus TryRemoveArgs(ConsumerView<PcqConsumer>& aView, Arg& aArg,
Args&... aArgs) {
QueueStatus status = TryCopyItem(aView, aArg);
return IsSuccess(status) ? TryRemoveArgs(aView, aArgs...) : status;
}
QueueStatus TryRemoveArgs(ConsumerView<PcqConsumer>&) {
return QueueStatus::kSuccess;
}
// If an item is available then it is copied into aArg. The item is skipped
// over if aArg is null.
template <typename Arg>
QueueStatus TryCopyItem(ConsumerView<PcqConsumer>& aView, Arg& aArg) {
MOZ_ASSERT(aArg);
return QueueParamTraits<typename RemoveCVR<Arg>::Type>::Read(
aView, const_cast<std::remove_cv_t<Arg>*>(&aArg));
}
template <typename Arg>
QueueStatus ReadObject(size_t* aRead, size_t aWrite, Arg* arg,
size_t aArgSize) {
return Marshaller::ReadObject(mQueue, QueueBufferSize(), aRead, aWrite, arg,
aArgSize);
}
// Currently, the PCQ requires any parameters expected to need more than
// 1/16 the total number of bytes in the command queue to use their own
// SharedMemory.
bool NeedsSharedMemory(size_t aRequested) {
return (Size() / 16) < aRequested;
}
PcqConsumer(Shmem& aShmem, IProtocol* aProtocol, size_t aQueueSize,
RefPtr<detail::PcqRCSemaphore> aMaybeNotEmptySem,
RefPtr<detail::PcqRCSemaphore> aMaybeNotFullSem)
: PcqBase(aShmem, aProtocol, aQueueSize, aMaybeNotEmptySem,
aMaybeNotFullSem) {}
PcqConsumer(const PcqConsumer&) = delete;
PcqConsumer& operator=(const PcqConsumer&) = delete;
};
using mozilla::detail::GetCacheLineSize;
using mozilla::detail::GetMaxHeaderSize;
/**
* A single producer + single consumer queue, implemented as a
* circular queue. The object is backed with a Shmem, which allows
* it to be used across processes.
*
* This is a single-producer/single-consumer queue. Another way of saying that
* is to say that the PcqProducer and PcqConsumer objects are not thread-safe.
*/
class ProducerConsumerQueue {
public:
/**
* Create a queue whose endpoints are the same as those of aProtocol.
* In choosing a queueSize, be aware that both the queue and the Shmem will
* allocate additional shared memory for internal accounting (see
* GetMaxHeaderSize) and that Shmem sizes are a multiple of the operating
* system's page sizes.
*
* aAdditionalBytes of shared memory will also be allocated.
* Clients may use this shared memory for their own purposes.
* See GetUserReservedMemory() and GetUserReservedMemorySize()
*/
static UniquePtr<ProducerConsumerQueue> Create(IProtocol* aProtocol,
size_t aQueueSize,
size_t aAdditionalBytes = 0) {
MOZ_ASSERT(aProtocol);
// Protocol must subclass PcqActor
MOZ_ASSERT(PcqActor::LookupProtocol(aProtocol));
Shmem shmem;
// NB: We need one extra byte for the queue contents (hence the "+1").
uint32_t totalShmemSize =
aQueueSize + 1 + GetMaxHeaderSize() + aAdditionalBytes;
if (!aProtocol->AllocUnsafeShmem(
totalShmemSize, mozilla::ipc::SharedMemory::TYPE_BASIC, &shmem)) {
return nullptr;
}
// NB: We need one extra byte for the queue contents (hence the "+1").
if ((!shmem.IsWritable()) || (!shmem.IsReadable()) ||
((GetMaxHeaderSize() + aQueueSize + 1) > totalShmemSize)) {
return nullptr;
}
return WrapUnique(new ProducerConsumerQueue(shmem, aProtocol, aQueueSize,
aAdditionalBytes));
}
/**
* The queue needs a few bytes for 2 shared counters. It takes these from the
* underlying Shmem. This will still work if the cache line size is incorrect
* for some architecture but operations may be less efficient.
*/
static constexpr size_t GetMaxHeaderSize() {
return mozilla::detail::GetMaxHeaderSize();
}
/**
* Cache line size for the machine. We assume a 64-byte cache line size.
*/
static constexpr size_t GetCacheLineSize() {
return mozilla::detail::GetCacheLineSize();
}
using Producer = PcqProducer;
using Consumer = PcqConsumer;
UniquePtr<Producer> TakeProducer() { return std::move(mProducer); }
UniquePtr<Consumer> TakeConsumer() { return std::move(mConsumer); }
private:
ProducerConsumerQueue(Shmem& aShmem, IProtocol* aProtocol, size_t aQueueSize,
size_t aAdditionalBytes) {
auto notempty = MakeRefPtr<detail::PcqRCSemaphore>(
CrossProcessSemaphore::Create("webgl-notempty", 0));
auto notfull = MakeRefPtr<detail::PcqRCSemaphore>(
CrossProcessSemaphore::Create("webgl-notfull", 1));
mProducer = WrapUnique(
new Producer(aShmem, aProtocol, aQueueSize, notempty, notfull));
mConsumer = WrapUnique(
new Consumer(aShmem, aProtocol, aQueueSize, notempty, notfull));
// The system may have reserved more bytes than the user asked for.
// Make sure they aren't given access to the extra.
MOZ_ASSERT(mProducer->mUserReservedSize >= aAdditionalBytes);
mProducer->mUserReservedSize = aAdditionalBytes;
mConsumer->mUserReservedSize = aAdditionalBytes;
if (aAdditionalBytes == 0) {
mProducer->mUserReservedMemory = nullptr;
mConsumer->mUserReservedMemory = nullptr;
}
PCQ_LOGD(
"Constructed PCQ (%p). Shmem Size = %zu. Queue Size = %zu. "
"Other process ID: %08x.",
this, aShmem.Size<uint8_t>(), aQueueSize,
(uint32_t)aProtocol->OtherPid());
}
UniquePtr<Producer> mProducer;
UniquePtr<Consumer> mConsumer;
};
} // namespace webgl
namespace ipc {
template <>
struct IPDLParamTraits<mozilla::detail::PcqBase> {
typedef mozilla::detail::PcqBase paramType;
static void Write(IPC::Message* aMsg, IProtocol* aActor, paramType& aParam) {
// Must be sent using the queue's underlying actor, which must still exist!
MOZ_RELEASE_ASSERT(aParam.mActor && aActor->Id() == aParam.mActor->Id());
WriteIPDLParam(aMsg, aActor, aParam.mActor->Id());
WriteIPDLParam(aMsg, aActor, aParam.QueueSize());
WriteIPDLParam(aMsg, aActor, std::move(aParam.mShmem));
// May not currently share a PcqProducer or PcqConsumer with a process that
// it's Shmem is not related to.
MOZ_ASSERT(aActor->OtherPid() == aParam.mOtherPid);
WriteIPDLParam(
aMsg, aActor,
aParam.mMaybeNotEmptySem->ShareToProcess(aActor->OtherPid()));
WriteIPDLParam(aMsg, aActor,
aParam.mMaybeNotFullSem->ShareToProcess(aActor->OtherPid()));
}
static bool Read(const IPC::Message* aMsg, PickleIterator* aIter,
IProtocol* aActor, paramType* aResult) {
int32_t iProtocolId;
size_t queueSize;
Shmem shmem;
CrossProcessSemaphoreHandle notEmptyHandle;
CrossProcessSemaphoreHandle notFullHandle;
if (!ReadIPDLParam(aMsg, aIter, aActor, &iProtocolId) ||
(iProtocolId != aActor->Id()) ||
!ReadIPDLParam(aMsg, aIter, aActor, &queueSize) ||
!ReadIPDLParam(aMsg, aIter, aActor, &shmem) ||
!ReadIPDLParam(aMsg, aIter, aActor, &notEmptyHandle) ||
!ReadIPDLParam(aMsg, aIter, aActor, &notFullHandle)) {
return false;
}
MOZ_ASSERT(IsHandleValid(notEmptyHandle) && IsHandleValid(notFullHandle));
aResult->Set(shmem, aActor, queueSize,
MakeRefPtr<detail::PcqRCSemaphore>(
CrossProcessSemaphore::Create(notEmptyHandle)),
MakeRefPtr<detail::PcqRCSemaphore>(
CrossProcessSemaphore::Create(notFullHandle)));
return true;
}
static void Log(const paramType& aParam, std::wstring* aLog) {
IPDLParamTraits<Shmem>::Log(aParam.mShmem, aLog);
}
};
template <>
struct IPDLParamTraits<mozilla::webgl::PcqProducer>
: public IPDLParamTraits<mozilla::detail::PcqBase> {
typedef mozilla::webgl::PcqProducer paramType;
};
template <>
struct IPDLParamTraits<mozilla::webgl::PcqConsumer>
: public IPDLParamTraits<mozilla::detail::PcqBase> {
typedef mozilla::webgl::PcqConsumer paramType;
};
} // namespace ipc
} // namespace mozilla
#endif // mozilla_ipc_ProducerConsumerQueue_h

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

@ -1,13 +0,0 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ProducerConsumerQueue.h"
namespace mozilla::webgl {
mozilla::LazyLogModule gPCQLog("pcq");
mozilla::LazyLogModule gIpdlQueueLog("ipdlqueue");
} // namespace mozilla::webgl

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

@ -8,18 +8,10 @@
#include <type_traits>
#include "mozilla/FunctionTypeTraits.h"
#include "mozilla/dom/ProducerConsumerQueue.h"
#include "mozilla/ipc/IPDLParamTraits.h"
#include "QueueParamTraits.h"
#include "WebGLTypes.h"
// Get around a bug in Clang related to __thiscall method pointers
#if defined(_M_IX86)
# define SINK_FCN_CC __thiscall
#else
# define SINK_FCN_CC
#endif
namespace mozilla {
using webgl::QueueStatus;
@ -169,486 +161,6 @@ inline bool Deserialize(RangeConsumerView& view, Arg& arg, Args&... args) {
} // namespace webgl
// -
using mozilla::ipc::IPDLParamTraits;
enum CommandResult { kSuccess, kTimeExpired, kQueueEmpty, kError };
enum CommandSyncType { ASYNC, SYNC };
/**
* A CommandSource is obtained from a CommandQueue. Use it by inserting a
* command (represented by type Command) using InsertCommand, which also
* needs all parameters to the command. They are then serialized and sent
* to the CommandSink, which must understand the Command+Args combination
* to execute it.
*/
template <typename Command, typename _Source>
class CommandSource {
using Source = _Source;
public:
explicit CommandSource(UniquePtr<Source>&& aSource)
: mSource(std::move(aSource)) {
MOZ_ASSERT(mSource);
}
template <typename... Args>
QueueStatus InsertCommand(Command aCommand, Args&&... aArgs) {
return this->mSource->TryWaitInsert(Nothing() /* wait forever */, aCommand,
aArgs...);
}
QueueStatus InsertCommand(Command aCommand) {
return this->mSource->TryWaitInsert(Nothing() /* wait forever */, aCommand);
}
template <typename... Args>
QueueStatus RunCommand(Command aCommand, Args&&... aArgs) {
return InsertCommand(aCommand, std::forward<Args>(aArgs)...);
}
// For IPDL:
CommandSource() = default;
protected:
friend struct IPDLParamTraits<mozilla::CommandSource<Command, Source>>;
UniquePtr<Source> mSource;
};
/**
* A CommandSink is obtained from a CommandQueue. It executes commands that
* originated in its CommandSource. Use this class by calling one of the
* Process methods, which will autonomously deserialize, dispatch and
* post-process the execution. This class handles deserialization -- dispatch
* and processing are to be provided by a subclass in its implementation of the
* pure-virtual DispatchCommand method. DispatchCommand implementations can
* easily run functions and methods using arguments taken from the command
* queue by calling the Dispatch methods in this class.
*/
template <typename Command, typename _Sink>
class CommandSink {
using Sink = _Sink;
public:
explicit CommandSink(UniquePtr<Sink>&& aSink) : mSink(std::move(aSink)) {
MOZ_ASSERT(mSink);
}
/**
* Attempts to process the next command in the queue, if one is available.
*/
CommandResult ProcessOne(const Maybe<TimeDuration>& aTimeout) {
Command command;
QueueStatus status = (aTimeout.isNothing() || aTimeout.value())
? this->mSink->TryWaitRemove(aTimeout, command)
: this->mSink->TryRemove(command);
if (status == QueueStatus::kSuccess) {
if (DispatchCommand(command)) {
return CommandResult::kSuccess;
}
return CommandResult::kError;
}
if (status == QueueStatus::kNotReady) {
return CommandResult::kQueueEmpty;
}
if (status == QueueStatus::kOOMError) {
ReportOOM();
}
return CommandResult::kError;
}
CommandResult ProcessOneNow() { return ProcessOne(Some(TimeDuration(0))); }
/**
* Drains the queue until the queue is empty or an error occurs, whichever
* comes first.
* Returns the result of the last attempt to process a command, which will
* be either QueueEmpty or Error.
*/
CommandResult ProcessAll() {
CommandResult result;
do {
result = ProcessOneNow();
} while (result == CommandResult::kSuccess);
return result;
}
/**
* Drains the queue until aDuration expires, the queue is empty, or an error
* occurs, whichever comes first.
* Returns the result of the last attempt to process a command.
*/
CommandResult ProcessUpToDuration(TimeDuration aDuration) {
TimeStamp start = TimeStamp::Now();
TimeStamp now = start;
CommandResult result;
do {
result = ProcessOne(Some(aDuration - (now - start)));
now = TimeStamp::Now();
} while ((result == CommandResult::kSuccess) &&
((now - start) < aDuration));
return result;
}
// For IPDL:
CommandSink() = default;
// non-void return value, non-const method variant
template <typename T, typename ReturnType, typename... Args>
bool DispatchAsyncMethod(T& aObj, ReturnType (T::*aMethod)(Args...)) {
std::tuple<std::remove_cv_t<std::remove_reference_t<Args>>...> args;
if (!ReadArgs(args)) {
return false;
}
CallMethod(aObj, aMethod, args, std::index_sequence_for<Args...>{});
return true;
}
// non-void return value, const method variant
template <typename T, typename ReturnType, typename... Args>
bool DispatchAsyncMethod(const T& aObj,
ReturnType (T::*aMethod)(Args...) const) {
std::tuple<std::remove_cv_t<std::remove_reference_t<Args>>...> args;
if (!ReadArgs(args)) {
return false;
}
CallMethod(aObj, aMethod, args, std::index_sequence_for<Args...>{});
return true;
}
// void return value, non-const method variant
template <typename T, typename... Args>
bool DispatchAsyncMethod(T* aObj, void (T::*aMethod)(Args...)) {
std::tuple<std::remove_cv_t<std::remove_reference_t<Args>>...> args;
if (!ReadArgs(args)) {
return false;
}
CallVoidMethod(aObj, aMethod, args, std::index_sequence_for<Args...>{});
return true;
}
// void return value, const method variant
template <typename T, typename... Args>
bool DispatchAsyncMethod(const T* aObj, void (T::*aMethod)(Args...) const) {
std::tuple<std::remove_cv_t<std::remove_reference_t<Args>>...> args;
if (!ReadArgs(args)) {
return false;
}
CallVoidMethod(aObj, aMethod, args, std::index_sequence_for<Args...>{});
return true;
}
protected:
friend struct IPDLParamTraits<mozilla::CommandSink<Command, Sink>>;
/**
* Implementations will usually be something like a big switch statement
* that calls one of the Dispatch methods in this class.
*/
virtual bool DispatchCommand(Command command) = 0;
/**
* Implementations can override this to detect out-of-memory during
* deserialization.
*/
virtual void ReportOOM() {}
template <typename... Args, size_t... Indices>
QueueStatus CallTryRemove(std::tuple<Args...>& aArgs,
std::index_sequence<Indices...>) {
QueueStatus status = mSink->TryRemove(std::get<Indices>(aArgs)...);
// The CommandQueue inserts the command and the args together as an atomic
// operation. We already read the command so the args must also be
// available.
MOZ_ASSERT(status != QueueStatus::kNotReady);
return status;
}
QueueStatus CallTryRemove(std::tuple<>& aArgs,
std::make_integer_sequence<size_t, 0>) {
return QueueStatus::kSuccess;
}
template <typename T, typename MethodType, typename... Args,
size_t... Indices,
typename ReturnType =
typename mozilla::FunctionTypeTraits<MethodType>::ReturnType>
ReturnType CallMethod(T& aObj, MethodType aMethod, std::tuple<Args...>& aArgs,
std::index_sequence<Indices...>) {
return (aObj.*aMethod)(std::forward<Args>(std::get<Indices>(aArgs))...);
}
template <typename T, typename MethodType, typename... Args,
size_t... Indices>
void CallVoidMethod(T& aObj, MethodType aMethod, std::tuple<Args...>& aArgs,
std::index_sequence<Indices...>) {
(aObj.*aMethod)(std::forward<Args>(std::get<Indices>(aArgs))...);
}
template <typename... Args>
bool ReadArgs(std::tuple<Args...>& aArgs) {
QueueStatus status =
CallTryRemove(aArgs, std::index_sequence_for<Args...>{});
return IsSuccess(status);
}
UniquePtr<Sink> mSink;
};
enum SyncResponse : uint8_t { RESPONSE_NAK, RESPONSE_ACK };
/**
* This is the Source for a SyncCommandSink. It takes an extra queue,
* the ResponseQueue, and uses it to receive synchronous responses from
* the sink. The ResponseQueue is a regular queue, not a CommandQueue.
*/
template <typename Command, typename _Source, typename _ResponseQueue>
class SyncCommandSource : public CommandSource<Command, _Source> {
public:
using BaseType = CommandSource<Command, _Source>;
using Source = _Source;
using ResponseQueue = _ResponseQueue;
using ResponseSink = typename ResponseQueue::Consumer;
SyncCommandSource(UniquePtr<Source>&& aSource,
UniquePtr<ResponseSink>&& aResponseSink)
: CommandSource<Command, Source>(std::move(aSource)),
mResponseSink(std::move(aResponseSink)) {}
template <typename... Args>
QueueStatus RunAsyncCommand(Command aCommand, Args&&... aArgs) {
return this->RunCommand(aCommand, std::forward<Args>(aArgs)...);
}
template <typename... Args>
QueueStatus RunVoidSyncCommand(Command aCommand, Args&&... aArgs) {
QueueStatus status =
RunAsyncCommand(aCommand, std::forward<Args>(aArgs)...);
return IsSuccess(status) ? this->ReadSyncResponse() : status;
}
template <typename ResultType, typename... Args>
QueueStatus RunSyncCommand(Command aCommand, ResultType& aReturn,
Args&&... aArgs) {
QueueStatus status =
RunVoidSyncCommand(aCommand, std::forward<Args>(aArgs)...);
return IsSuccess(status) ? this->ReadResult(aReturn) : status;
}
// for IPDL:
SyncCommandSource() = default;
friend struct mozilla::ipc::IPDLParamTraits<
SyncCommandSource<Command, Source, ResponseQueue>>;
protected:
QueueStatus ReadSyncResponse() {
SyncResponse response;
QueueStatus status =
mResponseSink->TryWaitRemove(Nothing() /* wait forever */, response);
MOZ_ASSERT(status != QueueStatus::kNotReady);
if (IsSuccess(status) && response != RESPONSE_ACK) {
return QueueStatus::kFatalError;
}
return status;
}
template <typename T>
QueueStatus ReadResult(T& aResult) {
QueueStatus status = mResponseSink->TryRemove(aResult);
// The Sink posts the response code and result as an atomic transaction. We
// already read the response code so the result must be available.
MOZ_ASSERT(status != QueueStatus::kNotReady);
return status;
}
UniquePtr<ResponseSink> mResponseSink;
};
/**
* This is the Sink for a SyncCommandSource. It takes an extra queue, the
* ResponseQueue, and uses it to issue synchronous responses to the client.
* Subclasses can use the DispatchSync methods in this class in their
* DispatchCommand implementations.
* The ResponseQueue is not a CommandQueue.
*/
template <typename Command, typename _Sink, typename _ResponseQueue>
class SyncCommandSink : public CommandSink<Command, _Sink> {
using BaseType = CommandSink<Command, _Sink>;
using ResponseQueue = _ResponseQueue;
using Sink = _Sink;
using ResponseSource = typename ResponseQueue::Producer;
public:
SyncCommandSink(UniquePtr<Sink>&& aSink,
UniquePtr<ResponseSource>&& aResponseSource)
: CommandSink<Command, Sink>(std::move(aSink)),
mResponseSource(std::move(aResponseSource)) {
MOZ_ASSERT(mResponseSource);
}
// for IPDL:
SyncCommandSink() = default;
friend struct mozilla::ipc::IPDLParamTraits<
SyncCommandSink<Command, Sink, ResponseQueue>>;
// Places RESPONSE_ACK and the typed return value, or RESPONSE_NAK, in
// the response queue,
// __cdecl/__thiscall non-const method variant.
template <typename T, typename ReturnType, typename... Args>
bool DispatchSyncMethod(T& aObj,
ReturnType SINK_FCN_CC (T::*aMethod)(Args...)) {
std::tuple<std::remove_cv_t<std::remove_reference_t<Args>>...> args;
if (!BaseType::ReadArgs(args)) {
WriteNAK();
return false;
}
ReturnType response = BaseType::CallMethod(
aObj, aMethod, args, std::index_sequence_for<Args...>{});
return WriteACK(response);
}
// __cdecl/__thiscall const method variant.
template <typename T, typename ReturnType, typename... Args>
bool DispatchSyncMethod(const T& aObj,
ReturnType SINK_FCN_CC (T::*aMethod)(Args...) const) {
std::tuple<std::remove_cv_t<std::remove_reference_t<Args>>...> args;
if (!BaseType::ReadArgs(args)) {
WriteNAK();
return false;
}
ReturnType response = BaseType::CallMethod(
aObj, aMethod, args, std::index_sequence_for<Args...>{});
return WriteACK(response);
}
#if defined(_M_IX86)
// __stdcall non-const method variant.
template <typename T, typename ReturnType, typename... Args>
bool DispatchSyncMethod(T& aObj,
ReturnType __stdcall (T::*aMethod)(Args...)) {
std::tuple<std::remove_cv_t<std::remove_reference_t<Args>>...> args;
if (!BaseType::ReadArgs(args)) {
WriteNAK();
return false;
}
ReturnType response = BaseType::CallMethod(
aObj, aMethod, args, std::index_sequence_for<Args...>{});
return WriteACK(response);
}
// __stdcall const method variant.
template <typename T, typename ReturnType, typename... Args>
bool DispatchSyncMethod(const T& aObj,
ReturnType __stdcall (T::*aMethod)(Args...) const) {
std::tuple<std::remove_cv_t<std::remove_reference_t<Args>>...> args;
if (!BaseType::ReadArgs(args)) {
WriteNAK();
return false;
}
ReturnType response = BaseType::CallMethod(
aObj, aMethod, args, std::index_sequence_for<Args...>{});
return WriteACK(response);
}
#endif
// __cdecl/__thiscall non-const void method variant
template <typename T, typename... Args>
bool DispatchSyncMethod(T& aObj, void SINK_FCN_CC (T::*aMethod)(Args...)) {
std::tuple<std::remove_cv_t<std::remove_reference_t<Args>>...> args;
if (!BaseType::ReadArgs(args)) {
WriteNAK();
return false;
}
BaseType::CallVoidMethod(aObj, aMethod, args,
std::index_sequence_for<Args...>{});
return WriteACK();
}
// __cdecl/__thiscall const void method variant
template <typename T, typename... Args>
bool DispatchSyncMethod(const T& aObj,
void SINK_FCN_CC (T::*aMethod)(Args...) const) {
std::tuple<std::remove_cv_t<std::remove_reference_t<Args>>...> args;
if (!BaseType::ReadArgs(args)) {
WriteNAK();
return false;
}
BaseType::CallVoidMethod(aObj, aMethod, args,
std::index_sequence_for<Args...>{});
return WriteACK();
}
#if defined(_M_IX86)
// __stdcall non-const void method variant
template <typename T, typename... Args>
bool DispatchSyncMethod(T& aObj, void __stdcall (T::*aMethod)(Args...)) {
std::tuple<std::remove_cv_t<std::remove_reference_t<Args>>...> args;
if (!BaseType::ReadArgs(args)) {
WriteNAK();
return false;
}
BaseType::CallVoidMethod(aObj, aMethod, args,
std::index_sequence_for<Args...>{});
return WriteACK();
}
// __stdcall const void method variant
template <typename T, typename... Args>
bool DispatchSyncMethod(const T& aObj,
void __stdcall (T::*aMethod)(Args...) const) {
std::tuple<std::remove_cv_t<std::remove_reference_t<Args>>...> args;
if (!BaseType::ReadArgs(args)) {
WriteNAK();
return false;
}
BaseType::CallVoidMethod(aObj, aMethod, args,
std::index_sequence_for<Args...>{});
return WriteACK();
}
#endif
protected:
template <typename... Args>
bool WriteArgs(const Args&... aArgs) {
return IsSuccess(mResponseSource->TryInsert(aArgs...));
}
template <typename... Args>
bool WriteACK(const Args&... aArgs) {
SyncResponse ack = RESPONSE_ACK;
return WriteArgs(ack, aArgs...);
}
bool WriteNAK() {
SyncResponse nak = RESPONSE_NAK;
return WriteArgs(nak);
}
UniquePtr<ResponseSource> mResponseSource;
};
// The MethodDispatcher setup uses a CommandSink to read parameters, call the
// given method using the given synchronization protocol, and provide
// compile-time lookup of the ID by class method.
@ -667,8 +179,7 @@ class SyncCommandSink : public CommandSink<Command, _Sink> {
// template <>
// class MyDispatcher<0>
// : public MethodDispatcher<MyDispatcher, 0,
// decltype(&MyClass::MyMethod), MyClass::MyMethod,
// CommandSyncType::ASYNC> {};
// decltype(&MyClass::MyMethod), MyClass::MyMethod> {};
//
// The method may then be called from the source and run on the sink.
//
@ -683,9 +194,6 @@ class EmptyMethodDispatcher {
webgl::RangeConsumerView&) {
MOZ_CRASH("Illegal ID in DispatchCommand");
}
static MOZ_ALWAYS_INLINE CommandSyncType SyncType(size_t) {
MOZ_CRASH("Illegal ID in SyncType");
}
};
// -
@ -704,7 +212,7 @@ std::tuple<std::remove_cv_t<std::remove_reference_t<Args>>...> ArgsTuple(
// Derived type must be parameterized by the ID.
template <template <size_t> typename Derived, size_t ID, typename MethodType,
MethodType method, CommandSyncType syncType>
MethodType method>
class MethodDispatcher {
static constexpr size_t kId = ID;
using DerivedType = Derived<ID>;
@ -728,97 +236,10 @@ class MethodDispatcher {
return Derived<kId + 1>::DispatchCommand(obj, id, view);
}
static MOZ_ALWAYS_INLINE CommandSyncType SyncType(size_t aId) {
return (aId == kId) ? syncType : NextDispatcher::SyncType(kId);
}
static constexpr CommandSyncType SyncType() { return syncType; }
static constexpr size_t Id() { return kId; }
static constexpr MethodType Method() { return method; }
};
namespace ipc {
template <typename T>
struct IPDLParamTraits;
template <typename Command, typename Source>
struct IPDLParamTraits<mozilla::CommandSource<Command, Source>> {
public:
typedef mozilla::CommandSource<Command, Source> paramType;
static void Write(IPC::Message* aMsg, IProtocol* aActor,
const paramType& aParam) {
WriteIPDLParam(aMsg, aActor, aParam.mSource);
}
static bool Read(const IPC::Message* aMsg, PickleIterator* aIter,
IProtocol* aActor, paramType* aResult) {
return ReadIPDLParam(aMsg, aIter, aActor, &aResult->mSource);
}
};
template <typename Command, typename Sink>
struct IPDLParamTraits<mozilla::CommandSink<Command, Sink>> {
public:
typedef mozilla::CommandSink<Command, Sink> paramType;
static void Write(IPC::Message* aMsg, IProtocol* aActor,
const paramType& aParam) {
WriteIPDLParam(aMsg, aActor, aParam.mSink);
}
static bool Read(const IPC::Message* aMsg, PickleIterator* aIter,
IProtocol* aActor, paramType* aResult) {
return ReadIPDLParam(aMsg, aIter, aActor, &aResult->mSink);
}
};
template <typename Command, typename Source, typename ResponseQueue>
struct IPDLParamTraits<
mozilla::SyncCommandSource<Command, Source, ResponseQueue>>
: public IPDLParamTraits<mozilla::CommandSource<Command, Source>> {
public:
typedef mozilla::SyncCommandSource<Command, Source, ResponseQueue> paramType;
typedef typename paramType::BaseType paramBaseType;
static void Write(IPC::Message* aMsg, IProtocol* aActor,
const paramType& aParam) {
WriteIPDLParam(aMsg, aActor, static_cast<const paramBaseType&>(aParam));
WriteIPDLParam(aMsg, aActor, aParam.mResponseSink);
}
static bool Read(const IPC::Message* aMsg, PickleIterator* aIter,
IProtocol* aActor, paramType* aParam) {
bool result =
ReadIPDLParam(aMsg, aIter, aActor, static_cast<paramBaseType*>(aParam));
return result && ReadIPDLParam(aMsg, aIter, aActor, &aParam->mResponseSink);
}
};
template <typename Command, typename Sink, typename ResponseQueue>
struct IPDLParamTraits<mozilla::SyncCommandSink<Command, Sink, ResponseQueue>>
: public IPDLParamTraits<mozilla::CommandSink<Command, Sink>> {
public:
typedef mozilla::SyncCommandSink<Command, Sink, ResponseQueue> paramType;
typedef typename paramType::BaseType paramBaseType;
static void Write(IPC::Message* aMsg, IProtocol* aActor,
const paramType& aParam) {
WriteIPDLParam(aMsg, aActor, static_cast<const paramBaseType&>(aParam));
WriteIPDLParam(aMsg, aActor, aParam.mResponseSource);
}
static bool Read(const IPC::Message* aMsg, PickleIterator* aIter,
IProtocol* aActor, paramType* aParam) {
bool result =
ReadIPDLParam(aMsg, aIter, aActor, static_cast<paramBaseType*>(aParam));
return result &&
ReadIPDLParam(aMsg, aIter, aActor, &aParam->mResponseSource);
}
};
} // namespace ipc
} // namespace mozilla
#endif // WEBGLCOMMANDQUEUE_H_

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

@ -1,21 +0,0 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "WebGLCrossProcessCommandQueue.h"
#include "WebGLMethodDispatcher.h"
namespace mozilla {
#if 0
bool HostWebGLCommandSink<Consumer, Queue>::DispatchCommand(size_t command) {
if (!mHostContext) {
return false;
}
return WebGLMethodDispatcher::DispatchCommand(command, *this, *mHostContext);
}
#endif
} // namespace mozilla

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

@ -1,97 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef WEBGLCROSSPROCESSCOMMANDQUEUE_H_
#define WEBGLCROSSPROCESSCOMMANDQUEUE_H_
#include "mozilla/dom/WebGLCommandQueue.h"
#include "ProducerConsumerQueue.h"
#include "IpdlQueue.h"
namespace mozilla {
namespace dom {
class WebGLParent;
class WebGLChild;
} // namespace dom
namespace layers {
class PCompositorBridgeParent;
}
class HostWebGLContext;
using mozilla::webgl::ProducerConsumerQueue;
/**
* The source for the WebGL Command Queue.
*/
using ClientWebGLCommandSourceP =
SyncCommandSource<size_t, mozilla::webgl::PcqProducer,
mozilla::webgl::ProducerConsumerQueue>;
/**
* The sink for the WebGL Command Queue. This object is created in the client
* and sent to the host, where it needs to be given a HostWebGLContext that it
* then uses for executing methods. Add new commands to DispatchCommand using
* the WEBGL_SYNC_COMMAND and WEBGL_ASYNC_COMMAND macros.
*/
template <typename Consumer, typename Queue>
class HostWebGLCommandSink final
: public SyncCommandSink<size_t, Consumer, Queue> {
public:
HostWebGLCommandSink(UniquePtr<Consumer>&& aConsumer,
UniquePtr<typename Queue::Producer>&& aResponseProducer)
: SyncCommandSink<size_t, Consumer, Queue>(
std::move(aConsumer), std::move(aResponseProducer)) {}
HostWebGLContext* mHostContext = nullptr;
// For IPDL:
HostWebGLCommandSink() = default;
protected:
friend struct mozilla::ipc::IPDLParamTraits<HostWebGLCommandSink>;
friend class mozilla::layers::PCompositorBridgeParent;
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 {
template <typename Consumer, typename Queue>
struct IPDLParamTraits<mozilla::HostWebGLCommandSink<Consumer, Queue>>
: public IPDLParamTraits<
mozilla::SyncCommandSink<size_t, Consumer, Queue>> {
public:
typedef mozilla::HostWebGLCommandSink<Consumer, Queue> paramType;
};
} // namespace ipc
} // namespace mozilla
#endif // WEBGLCROSSPROCESSCOMMANDQUEUE_H_

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

@ -7,6 +7,8 @@
#define WEBGLIPDL_H_
#include "ipc/EnumSerializer.h"
#include "mozilla/ipc/IPDLParamTraits.h"
#include "mozilla/ipc/Shmem.h"
#include "mozilla/layers/LayersSurfaces.h"
#include "WebGLTypes.h"
@ -24,7 +26,7 @@ class RaiiShmem final {
/// Returns zeroed data.
static RaiiShmem Alloc(mozilla::ipc::IProtocol* const allocator,
const size_t size,
const Shmem::SharedMemory::SharedMemoryType type) {
const mozilla::ipc::SharedMemory::SharedMemoryType type) {
mozilla::ipc::Shmem shmem;
if (!allocator->AllocShmem(size, type, &shmem)) return {};
return {allocator, shmem};

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

@ -7,14 +7,11 @@
#define WEBGLMETHODDISPATCHER_H_
#include "TexUnpackBlob.h"
#include "WebGLCrossProcessCommandQueue.h"
#include "HostWebGLContext.h"
#include "WebGLQueueParamTraits.h"
namespace mozilla {
// The WebGLMethodDispatcher will dispatch commands read from the
// HostWebGLCommandSink and issue them to a given HostWebGLContext.
template <size_t id = 0>
class WebGLMethodDispatcher
: public EmptyMethodDispatcher<WebGLMethodDispatcher> {};
@ -22,11 +19,11 @@ class WebGLMethodDispatcher
template <typename MethodT, MethodT Method>
size_t IdByMethod() = delete;
#define DEFINE_METHOD_DISPATCHER(_ID, _METHOD, _SYNC) \
#define DEFINE_METHOD_DISPATCHER(_ID, _METHOD) \
template <> \
class WebGLMethodDispatcher<_ID> \
: public MethodDispatcher<WebGLMethodDispatcher, _ID, \
decltype(&_METHOD), &_METHOD, _SYNC> {}; \
decltype(&_METHOD), &_METHOD> {}; \
template <> \
inline size_t IdByMethod<decltype(&_METHOD), &_METHOD>() { \
return _ID; \
@ -34,14 +31,11 @@ size_t IdByMethod() = delete;
// Defines each method the WebGLMethodDispatcher handles. The COUNTER value
// is used as a cross-process ID for each of the methods.
#define DEFINE_METHOD_HELPER(_METHOD, _SYNC) \
DEFINE_METHOD_DISPATCHER(__COUNTER__, _METHOD, _SYNC)
#define DEFINE_ASYNC(_METHOD) \
DEFINE_METHOD_HELPER(_METHOD, CommandSyncType::ASYNC)
DEFINE_METHOD_DISPATCHER(__COUNTER__, _METHOD)
DEFINE_ASYNC(HostWebGLContext::CreateBuffer)
DEFINE_ASYNC(HostWebGLContext::CreateFramebuffer)
// DEFINE_SYNC(HostWebGLContext::CreateOpaqueFramebuffer)
DEFINE_ASYNC(HostWebGLContext::CreateProgram)
DEFINE_ASYNC(HostWebGLContext::CreateQuery)
DEFINE_ASYNC(HostWebGLContext::CreateRenderbuffer)
@ -67,26 +61,15 @@ DEFINE_ASYNC(HostWebGLContext::DeleteVertexArray)
DEFINE_ASYNC(HostWebGLContext::Disable)
DEFINE_ASYNC(HostWebGLContext::Enable)
DEFINE_ASYNC(HostWebGLContext::GenerateError)
// DEFINE_SYNC(HostWebGLContext::GetCompileResult)
// DEFINE_SYNC(HostWebGLContext::GetFrontBufferSnapshot)
// DEFINE_SYNC(HostWebGLContext::GetFragDataLocation)
// DEFINE_SYNC(HostWebGLContext::GetFrontBuffer)
// DEFINE_SYNC(HostWebGLContext::GetLinkResult)
// DEFINE_SYNC(HostWebGLContext::IsEnabled)
DEFINE_ASYNC(HostWebGLContext::Resize)
DEFINE_ASYNC(HostWebGLContext::RequestExtension)
// DEFINE_SYNC(HostWebGLContext::DrawingBufferSize)
// DEFINE_SYNC(HostWebGLContext::OnMemoryPressure)
DEFINE_ASYNC(HostWebGLContext::DidRefresh)
// DEFINE_SYNC(HostWebGLContext::GetParameter)
// DEFINE_SYNC(HostWebGLContext::GetString)
DEFINE_ASYNC(HostWebGLContext::AttachShader)
DEFINE_ASYNC(HostWebGLContext::BindAttribLocation)
DEFINE_ASYNC(HostWebGLContext::BindFramebuffer)
DEFINE_ASYNC(HostWebGLContext::BlendColor)
DEFINE_ASYNC(HostWebGLContext::BlendEquationSeparate)
DEFINE_ASYNC(HostWebGLContext::BlendFuncSeparate)
// DEFINE_SYNC(HostWebGLContext::CheckFramebufferStatus)
DEFINE_ASYNC(HostWebGLContext::Clear)
DEFINE_ASYNC(HostWebGLContext::ClearColor)
DEFINE_ASYNC(HostWebGLContext::ClearDepth)
@ -99,15 +82,8 @@ DEFINE_ASYNC(HostWebGLContext::DepthMask)
DEFINE_ASYNC(HostWebGLContext::DepthRange)
DEFINE_ASYNC(HostWebGLContext::DetachShader)
DEFINE_ASYNC(HostWebGLContext::Flush)
// DEFINE_SYNC(HostWebGLContext::Finish)
DEFINE_ASYNC(HostWebGLContext::FramebufferAttach)
DEFINE_ASYNC(HostWebGLContext::FrontFace)
// DEFINE_SYNC(HostWebGLContext::GetBufferParameter)
// DEFINE_SYNC(HostWebGLContext::GetError)
// DEFINE_SYNC(HostWebGLContext::GetFramebufferAttachmentParameter)
// DEFINE_SYNC(HostWebGLContext::GetRenderbufferParameter)
// DEFINE_SYNC(HostWebGLContext::GetShaderPrecisionFormat)
// DEFINE_SYNC(HostWebGLContext::GetUniform)
DEFINE_ASYNC(HostWebGLContext::Hint)
DEFINE_ASYNC(HostWebGLContext::LineWidth)
DEFINE_ASYNC(HostWebGLContext::LinkProgram)
@ -123,14 +99,12 @@ DEFINE_ASYNC(HostWebGLContext::Viewport)
DEFINE_ASYNC(HostWebGLContext::BindBuffer)
DEFINE_ASYNC(HostWebGLContext::BindBufferRange)
DEFINE_ASYNC(HostWebGLContext::CopyBufferSubData)
// DEFINE_ASYNC(HostWebGLContext::GetBufferSubData)
DEFINE_ASYNC(HostWebGLContext::BufferData)
DEFINE_ASYNC(HostWebGLContext::BufferSubData)
DEFINE_ASYNC(HostWebGLContext::BlitFramebuffer)
DEFINE_ASYNC(HostWebGLContext::InvalidateFramebuffer)
DEFINE_ASYNC(HostWebGLContext::InvalidateSubFramebuffer)
DEFINE_ASYNC(HostWebGLContext::ReadBuffer)
// DEFINE_SYNC(HostWebGLContext::GetInternalformatParameter)
DEFINE_ASYNC(HostWebGLContext::RenderbufferStorageMultisample)
DEFINE_ASYNC(HostWebGLContext::ActiveTexture)
DEFINE_ASYNC(HostWebGLContext::BindTexture)
@ -139,28 +113,21 @@ DEFINE_ASYNC(HostWebGLContext::CopyTexImage)
DEFINE_ASYNC(HostWebGLContext::TexStorage)
DEFINE_ASYNC(HostWebGLContext::TexImage)
DEFINE_ASYNC(HostWebGLContext::CompressedTexImage)
// DEFINE_SYNC(HostWebGLContext::GetTexParameter)
DEFINE_ASYNC(HostWebGLContext::TexParameter_base)
DEFINE_ASYNC(HostWebGLContext::UseProgram)
// DEFINE_SYNC(HostWebGLContext::ValidateProgram)
DEFINE_ASYNC(HostWebGLContext::UniformData)
DEFINE_ASYNC(HostWebGLContext::VertexAttrib4T)
DEFINE_ASYNC(HostWebGLContext::VertexAttribDivisor)
// DEFINE_SYNC(HostWebGLContext::GetIndexedParameter)
DEFINE_ASYNC(HostWebGLContext::UniformBlockBinding)
DEFINE_ASYNC(HostWebGLContext::EnableVertexAttribArray)
DEFINE_ASYNC(HostWebGLContext::DisableVertexAttribArray)
// DEFINE_SYNC(HostWebGLContext::GetVertexAttrib)
DEFINE_ASYNC(HostWebGLContext::VertexAttribPointer)
DEFINE_ASYNC(HostWebGLContext::ClearBufferTv)
DEFINE_ASYNC(HostWebGLContext::ClearBufferfi)
// DEFINE_SYNC(HostWebGLContext::ReadPixels)
DEFINE_ASYNC(HostWebGLContext::ReadPixelsPbo)
DEFINE_ASYNC(HostWebGLContext::BindSampler)
DEFINE_ASYNC(HostWebGLContext::SamplerParameteri)
DEFINE_ASYNC(HostWebGLContext::SamplerParameterf)
// DEFINE_SYNC(HostWebGLContext::GetSamplerParameter)
// DEFINE_SYNC(HostWebGLContext::ClientWaitSync)
DEFINE_ASYNC(HostWebGLContext::BindTransformFeedback)
DEFINE_ASYNC(HostWebGLContext::BeginTransformFeedback)
DEFINE_ASYNC(HostWebGLContext::EndTransformFeedback)
@ -174,13 +141,10 @@ DEFINE_ASYNC(HostWebGLContext::DrawElementsInstanced)
DEFINE_ASYNC(HostWebGLContext::BeginQuery)
DEFINE_ASYNC(HostWebGLContext::EndQuery)
DEFINE_ASYNC(HostWebGLContext::QueryCounter)
// DEFINE_SYNC(HostWebGLContext::GetQueryParameter)
DEFINE_ASYNC(HostWebGLContext::SetFramebufferIsInOpaqueRAF)
DEFINE_ASYNC(HostWebGLContext::ClearVRSwapChain)
#undef DEFINE_METHOD_HELPER
#undef DEFINE_ASYNC
//#undef DEFINE_SYNC
#undef DEFINE_METHOD_DISPATCHER
} // namespace mozilla

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

@ -6,7 +6,6 @@
#include "WebGLParent.h"
#include "WebGLChild.h"
#include "mozilla/dom/WebGLCrossProcessCommandQueue.h"
#include "mozilla/layers/LayerTransactionParent.h"
#include "mozilla/layers/TextureClientSharedSurface.h"
#include "ImageContainer.h"
@ -17,19 +16,9 @@ namespace mozilla::dom {
mozilla::ipc::IPCResult WebGLParent::RecvInitialize(
const webgl::InitContextDesc& desc,
UniquePtr<HostWebGLCommandSinkP>&& aSinkP,
UniquePtr<HostWebGLCommandSinkI>&& aSinkI,
webgl::InitContextResult* const out) {
auto remotingData = Some(HostWebGLContext::RemotingData{
*this, {}, // std::move(commandSink),
});
mHost = HostWebGLContext::Create(
{
{},
std::move(remotingData),
},
desc, out);
{nullptr, this}, desc, out);
if (!mHost && !out->error.size()) {
return IPC_FAIL(this, "Abnormally failed to create HostWebGLContext.");

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

@ -14,6 +14,7 @@
namespace mozilla {
class HostWebGLContext;
class WebGLChild;
namespace layers {
class SharedSurfaceTextureClient;
@ -30,8 +31,7 @@ class WebGLParent : public PWebGLParent, public SupportsWeakPtr {
using OtherSideActor = WebGLChild;
mozilla::ipc::IPCResult RecvInitialize(
const webgl::InitContextDesc&, UniquePtr<HostWebGLCommandSinkP>&& aSinkP,
UniquePtr<HostWebGLCommandSinkI>&& aSinkI, webgl::InitContextResult* out);
const webgl::InitContextDesc&, webgl::InitContextResult* out);
WebGLParent(); // For IPDL

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

@ -9,7 +9,6 @@
#include <type_traits>
#include "ipc/EnumSerializer.h"
#include "mozilla/dom/ProducerConsumerQueue.h"
#include "TexUnpackBlob.h"
#include "WebGLContext.h"
#include "WebGLTypes.h"

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

@ -61,12 +61,10 @@ EXPORTS.mozilla.dom += [
"ImageUtils.h",
"IpdlQueue.h",
"OffscreenCanvas.h",
"ProducerConsumerQueue.h",
"QueueParamTraits.h",
"TextMetrics.h",
"WebGLChild.h",
"WebGLCommandQueue.h",
"WebGLCrossProcessCommandQueue.h",
"WebGLIpdl.h",
"WebGLParent.h",
"WebGLTypes.h",
@ -100,7 +98,6 @@ UNIFIED_SOURCES += [
"ClientWebGLContext.cpp",
"ClientWebGLExtensions.cpp",
"HostWebGLContext.cpp",
"Queue.cpp",
"TexUnpackBlob.cpp",
"WebGL2Context.cpp",
"WebGL2ContextBuffers.cpp",
@ -128,7 +125,6 @@ UNIFIED_SOURCES += [
"WebGLContextValidate.cpp",
"WebGLContextVertexArray.cpp",
"WebGLContextVertices.cpp",
"WebGLCrossProcessCommandQueue.cpp",
"WebGLExtensionColorBufferFloat.cpp",
"WebGLExtensionColorBufferHalfFloat.cpp",
"WebGLExtensionCompressedTextureASTC.cpp",