Bug 1607940 - Stand up webgl.out-of-process:true path. r=handyman,nika,froydnj

* Use clearer pref names.
* Default (and only support) IPDL dispatching.
* Make DispatchCommands async-only.
* Sync ipdl command per sync webgl entrypoint.
  * Eat the boilerplate cost, since there's not too many.
* Run SerializedSize off same path as Serialize.
* All shmem uploads go through normal DispatchCommands.
* Defer pruning of dead code for now so we can iterate quickly.
* Use Read/Write(begin,end) instead of (begin,size).
  * This would have prevented a bug where we read/wrote N*sizeof(T)*sizeof(T).

Differential Revision: https://phabricator.services.mozilla.com/D81495
This commit is contained in:
Jeff Gilbert
2020-07-21 22:56:52 +00:00
parent 17cbdc33b7
commit f60d94e923
35 changed files with 1978 additions and 1122 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -731,13 +731,12 @@ class ClientWebGLContext final : public nsICanvasRenderingContextInternal,
const RefPtr<ClientWebGLExtensionLoseContext> mExtLoseContext; const RefPtr<ClientWebGLExtensionLoseContext> mExtLoseContext;
webgl::LossStatus mLossStatus = webgl::LossStatus::Ready; mutable std::shared_ptr<webgl::NotLostData> mNotLost;
bool mAwaitingRestore = false; mutable GLenum mNextError = 0;
mutable webgl::LossStatus mLossStatus = webgl::LossStatus::Ready;
mutable bool mAwaitingRestore = false;
// - // -
private:
std::shared_ptr<webgl::NotLostData> mNotLost;
mutable GLenum mNextError = 0;
public: public:
const auto& Limits() const { return mNotLost->info.limits; } const auto& Limits() const { return mNotLost->info.limits; }
@@ -755,14 +754,14 @@ class ClientWebGLContext final : public nsICanvasRenderingContextInternal,
// - // -
public: public:
void EmulateLoseContext(); void EmulateLoseContext() const;
void OnContextLoss(webgl::ContextLossReason); void OnContextLoss(webgl::ContextLossReason) const;
void RestoreContext(webgl::LossStatus requiredStatus); void RestoreContext(webgl::LossStatus requiredStatus) const;
private: private:
bool DispatchEvent(const nsAString&) const; bool DispatchEvent(const nsAString&) const;
void Event_webglcontextlost(); void Event_webglcontextlost() const;
void Event_webglcontextrestored(); void Event_webglcontextrestored() const;
bool CreateHostContext(const uvec2& requestedSize); bool CreateHostContext(const uvec2& requestedSize);
void ThrowEvent_WebGLContextCreationError(const std::string&) const; void ThrowEvent_WebGLContextCreationError(const std::string&) const;
@@ -853,6 +852,10 @@ class ClientWebGLContext final : public nsICanvasRenderingContextInternal,
EnqueueErrorImpl(error, text); EnqueueErrorImpl(error, text);
} }
void EnqueueError(const webgl::ErrorInfo& info) const {
EnqueueError(info.type, "%s", info.info.c_str());
}
template <typename... Args> template <typename... Args>
void EnqueueWarning(const char* const format, const Args&... args) const { void EnqueueWarning(const char* const format, const Args&... args) const {
EnqueueError(0, format, args...); EnqueueError(0, format, args...);
@@ -924,9 +927,6 @@ class ClientWebGLContext final : public nsICanvasRenderingContextInternal,
nsDisplayListBuilder* aBuilder, nsDisplayListBuilder* aBuilder,
layers::WebRenderCanvasData* aCanvasData) override; layers::WebRenderCanvasData* aCanvasData) override;
bool UpdateCompositableHandle(LayerTransactionChild* aLayerTransaction,
CompositableHandle aHandle) override;
// ------ // ------
int32_t GetWidth() override { return AutoAssertCast(DrawingBufferSize().x); } int32_t GetWidth() override { return AutoAssertCast(DrawingBufferSize().x); }
@@ -1026,6 +1026,11 @@ class ClientWebGLContext final : public nsICanvasRenderingContextInternal,
void Enable(GLenum cap) const; void Enable(GLenum cap) const;
bool IsEnabled(GLenum cap) const; bool IsEnabled(GLenum cap) const;
private:
Maybe<double> GetNumber(GLenum pname);
Maybe<std::string> GetString(GLenum pname);
public:
void GetParameter(JSContext* cx, GLenum pname, void GetParameter(JSContext* cx, GLenum pname,
JS::MutableHandle<JS::Value> retval, ErrorResult& rv, JS::MutableHandle<JS::Value> retval, ErrorResult& rv,
bool debug = false); bool debug = false);
@@ -1703,6 +1708,10 @@ class ClientWebGLContext final : public nsICanvasRenderingContextInternal,
} }
// ------------------------ Uniforms and attributes ------------------------ // ------------------------ Uniforms and attributes ------------------------
private:
Maybe<double> GetVertexAttribPriv(GLuint index, GLenum pname);
public: public:
void GetVertexAttrib(JSContext* cx, GLuint index, GLenum pname, void GetVertexAttrib(JSContext* cx, GLuint index, GLenum pname,
JS::MutableHandle<JS::Value> retval, ErrorResult& rv); JS::MutableHandle<JS::Value> retval, ErrorResult& rv);
@@ -2079,61 +2088,6 @@ class ClientWebGLContext final : public nsICanvasRenderingContextInternal,
// The cross-process communication mechanism // The cross-process communication mechanism
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
protected: protected:
/*
template <size_t command, typename... Args>
void DispatchAsync(Args&&... aArgs) const {
const auto& oop = *mNotLost->outOfProcess;
QueueStatus status = oop.mCommandSource->RunAsyncCommand(command,
aArgs...);
if (!IsSuccess(status)) { if (status == QueueStatus::kOOMError) {
JsWarning("Ran out-of-memory during WebGL IPC.");
}
// Not much to do but shut down. Since this was a Pcq failure and
// may have been catastrophic, we don't try to revive it. Make sure to
// post "webglcontextlost"
MOZ_ASSERT_UNREACHABLE(
"TODO: Make this shut down the context, actors, everything.");
}
}
template <size_t command, typename ReturnType, typename... Args>
ReturnType DispatchSync(Args&&... aArgs) const {
const auto& oop = *mNotLost->outOfProcess;
ReturnType returnValue;
QueueStatus status =
oop.mCommandSource->RunSyncCommand(command, returnValue, aArgs...);
if (!IsSuccess(status)) {
if (status == QueueStatus::kOOMError) {
JsWarning("Ran out-of-memory during WebGL IPC.");
}
// Not much to do but shut down. Since this was a Pcq failure and
// may have been catastrophic, we don't try to revive it. Make sure to
// post "webglcontextlost"
MOZ_ASSERT_UNREACHABLE(
"TODO: Make this shut down the context, actors, everything.");
}
return returnValue;
}
template <size_t command, typename... Args>
void DispatchVoidSync(Args&&... aArgs) const {
const auto& oop = *mNotLost->outOfProcess;
const auto status =
oop.mCommandSource->RunVoidSyncCommand(command, aArgs...);
if (!IsSuccess(status)) {
if (status == QueueStatus::kOOMError) {
JsWarning("Ran out-of-memory during WebGL IPC.");
}
// Not much to do but shut down. Since this was a Pcq failure and
// may have been catastrophic, we don't try to revive it. Make sure to
// post "webglcontextlost"
MOZ_ASSERT_UNREACHABLE(
"TODO: Make this shut down the context, actors, everything.");
}
}
*/
template <typename ReturnType> template <typename ReturnType>
friend struct WebGLClientDispatcher; friend struct WebGLClientDispatcher;
@@ -2143,16 +2097,8 @@ class ClientWebGLContext final : public nsICanvasRenderingContextInternal,
// If we are running WebGL in this process then call the HostWebGLContext // If we are running WebGL in this process then call the HostWebGLContext
// method directly. Otherwise, dispatch over IPC. // method directly. Otherwise, dispatch over IPC.
// template <typename MethodType, MethodType method, template <typename MethodType, MethodType method, typename... Args>
// typename ReturnType = typename void Run(Args&&... aArgs) const;
// FunctionTypeTraits<MethodType>::ReturnType, size_t Id =
// WebGLMethodDispatcher::Id<MethodType, method>(), typename... Args>
// ReturnType Run(Args&&... aArgs) const;
template <
typename MethodType, MethodType method,
typename ReturnType = typename FunctionTypeTraits<MethodType>::ReturnType,
typename... Args>
ReturnType Run(Args&&... aArgs) const;
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// Helpers for DOM operations, composition, actors, etc // Helpers for DOM operations, composition, actors, etc

View File

@@ -191,11 +191,16 @@ class HostWebGLContext final : public SupportsWeakPtr<HostWebGLContext> {
Maybe<layers::SurfaceDescriptor> GetFrontBuffer(ObjectId xrFb, Maybe<layers::SurfaceDescriptor> GetFrontBuffer(ObjectId xrFb,
const bool webvr) const; const bool webvr) const;
RefPtr<gfx::DataSourceSurface> GetFrontBufferSnapshot() const { // -
return mContext->GetFrontBufferSnapshot();
uvec2 GetFrontBufferSize() const { return mContext->DrawingBufferSize(); }
bool FrontBufferSnapshotInto(Range<uint8_t> dest) const {
return mContext->FrontBufferSnapshotInto(dest);
} }
void ClearVRSwapChain() { mContext->ClearVRSwapChain(); } void ClearVRSwapChain() const { mContext->ClearVRSwapChain(); }
// -
void Resize(const uvec2& size) { return mContext->Resize(size); } void Resize(const uvec2& size) { return mContext->Resize(size); }
@@ -258,7 +263,7 @@ class HostWebGLContext final : public SupportsWeakPtr<HostWebGLContext> {
bool IsEnabled(GLenum cap) const { return mContext->IsEnabled(cap); } bool IsEnabled(GLenum cap) const { return mContext->IsEnabled(cap); }
Maybe<double> GetParameter(GLenum pname) const { Maybe<double> GetNumber(GLenum pname) const {
return mContext->GetParameter(pname); return mContext->GetParameter(pname);
} }
@@ -477,21 +482,21 @@ class HostWebGLContext final : public SupportsWeakPtr<HostWebGLContext> {
writeOffset, size); writeOffset, size);
} }
void GetBufferSubData(GLenum target, uint64_t srcByteOffset, bool GetBufferSubData(GLenum target, uint64_t srcByteOffset,
RawBuffer<uint8_t>& dest) const { const Range<uint8_t>& dest) const {
const auto range = MakeRange(dest); return GetWebGL2Context()->GetBufferSubData(target, srcByteOffset, dest);
GetWebGL2Context()->GetBufferSubData(target, srcByteOffset, range);
} }
void BufferData(GLenum target, const RawBuffer<const uint8_t>& data, void BufferData(GLenum target, const RawBuffer<>& data, GLenum usage) const {
GLenum usage) const { const auto& range = data.Data();
mContext->BufferData(target, data.Length(), data.Data(), usage); mContext->BufferData(target, range.length(), range.begin().get(), usage);
} }
void BufferSubData(GLenum target, uint64_t dstByteOffset, void BufferSubData(GLenum target, uint64_t dstByteOffset,
const RawBuffer<const uint8_t>& srcData) const { const RawBuffer<>& srcData) const {
mContext->BufferSubData(target, dstByteOffset, srcData.Length(), const auto& range = srcData.Data();
srcData.Data()); mContext->BufferSubData(target, dstByteOffset, range.length(),
range.begin().get());
} }
// -------------------------- Framebuffer Objects -------------------------- // -------------------------- Framebuffer Objects --------------------------
@@ -550,8 +555,7 @@ class HostWebGLContext final : public SupportsWeakPtr<HostWebGLContext> {
// CompressedTexSubImage if `sub` // CompressedTexSubImage if `sub`
void CompressedTexImage(bool sub, GLenum imageTarget, uint32_t level, void CompressedTexImage(bool sub, GLenum imageTarget, uint32_t level,
GLenum format, const uvec3& offset, const uvec3& size, GLenum format, const uvec3& offset, const uvec3& size,
const RawBuffer<const uint8_t>& src, const RawBuffer<>& src, const uint32_t pboImageSize,
const uint32_t pboImageSize,
const Maybe<uint64_t>& pboOffset) const { const Maybe<uint64_t>& pboOffset) const {
mContext->CompressedTexImage(sub, imageTarget, level, format, offset, size, mContext->CompressedTexImage(sub, imageTarget, level, format, offset, size,
MakeRange(src), pboImageSize, pboOffset); MakeRange(src), pboImageSize, pboOffset);
@@ -602,8 +606,8 @@ class HostWebGLContext final : public SupportsWeakPtr<HostWebGLContext> {
// ------------------------ Uniforms and attributes ------------------------ // ------------------------ Uniforms and attributes ------------------------
void UniformData(uint32_t loc, bool transpose, void UniformData(uint32_t loc, bool transpose,
const RawBuffer<const uint8_t>& data) const { const RawBuffer<>& data) const {
mContext->UniformData(loc, transpose, MakeRange(data)); mContext->UniformData(loc, transpose, data.Data());
} }
void VertexAttrib4T(GLuint index, const webgl::TypedQuad& data) const { void VertexAttrib4T(GLuint index, const webgl::TypedQuad& data) const {
@@ -660,10 +664,9 @@ class HostWebGLContext final : public SupportsWeakPtr<HostWebGLContext> {
mContext->ReadPixelsPbo(desc, offset); mContext->ReadPixelsPbo(desc, offset);
} }
void ReadPixels(const webgl::ReadPixelsDesc& desc, webgl::ReadPixelsResult ReadPixelsInto(const webgl::ReadPixelsDesc& desc,
RawBuffer<uint8_t>& dest) const { const Range<uint8_t>& dest) const {
const auto range = MakeRange(dest); return mContext->ReadPixelsInto(desc, dest);
mContext->ReadPixels(desc, range);
} }
// ----------------------------- Sampler ----------------------------------- // ----------------------------- Sampler -----------------------------------

View File

@@ -83,10 +83,6 @@ struct IpdlQueueBuffer {
using IpdlQueueBuffers = nsTArray<IpdlQueueBuffer>; 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;
static constexpr uint32_t kAsyncFlushWaitMs = 4; // 4ms static constexpr uint32_t kAsyncFlushWaitMs = 4; // 4ms
template <typename Derived> template <typename Derived>
@@ -432,10 +428,6 @@ class IpdlProducer final : public SupportsWeakPtr<IpdlProducer<_Actor>> {
arg, aArgSize); arg, aArgSize);
} }
inline bool NeedsSharedMemory(size_t aRequested) {
return aRequested >= kMaxIpdlQueueArgSize;
}
base::ProcessId OtherPid() { return mActor ? mActor->OtherPid() : 0; } base::ProcessId OtherPid() { return mActor ? mActor->OtherPid() : 0; }
protected: protected:
@@ -543,10 +535,6 @@ class IpdlConsumer final : public SupportsWeakPtr<IpdlConsumer<_Actor>> {
mBuf.Elements(), mBuf.Length() + 1, aRead, aWrite, arg, aArgSize); 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; } base::ProcessId OtherPid() { return mActor ? mActor->OtherPid() : 0; }
protected: protected:

View File

@@ -9,10 +9,25 @@ include protocol PCompositorBridge;
include protocol PLayerTransaction; 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::layers::SurfaceDescriptor from "mozilla/layers/LayersTypes.h";
using std::string from "ipc/IPCMessageUtils.h"; using std::string from "ipc/IPCMessageUtils.h";
using mozilla::uvec2 from "mozilla/dom/WebGLIpdl.h";
using mozilla::webgl::CompileResult from "mozilla/dom/WebGLIpdl.h";
using mozilla::webgl::ContextLossReason from "mozilla/dom/WebGLIpdl.h";
using mozilla::webgl::FrontBufferSnapshotIpc from "mozilla/dom/WebGLIpdl.h";
using mozilla::webgl::GetUniformData from "mozilla/dom/WebGLIpdl.h";
using mozilla::webgl::InitContextDesc from "mozilla/dom/WebGLIpdl.h"; using mozilla::webgl::InitContextDesc from "mozilla/dom/WebGLIpdl.h";
using mozilla::webgl::InitContextResult from "mozilla/dom/WebGLIpdl.h"; using mozilla::webgl::InitContextResult from "mozilla/dom/WebGLIpdl.h";
using mozilla::webgl::Int32Vector from "mozilla/dom/WebGLIpdl.h";
using mozilla::webgl::LinkResult from "mozilla/dom/WebGLIpdl.h";
using mozilla::webgl::MaybeDouble from "mozilla/dom/WebGLIpdl.h";
using mozilla::webgl::MaybeFrontBufferSnapshotIpc from "mozilla/dom/WebGLIpdl.h";
using mozilla::webgl::MaybeShaderPrecisionFormat from "mozilla/dom/WebGLIpdl.h";
using mozilla::webgl::MaybeSurfaceDescriptor from "mozilla/dom/WebGLIpdl.h";
using mozilla::webgl::MaybeString 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::HostWebGLCommandSinkP from "mozilla/dom/WebGLCrossProcessCommandQueue.h";
using mozilla::HostWebGLCommandSinkI 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::IpdlQueueBuffer from "mozilla/dom/IpdlQueue.h";
@@ -37,20 +52,53 @@ parent:
async __delete__(); async __delete__();
// DLP: TODO: Does this need to be sync? // -
sync UpdateCompositableHandle(PLayerTransaction aLayerTrans,
CompositableHandle aHandle);
sync ExchangeIpdlQueueData(IpdlQueueBuffer aMsg) returns (IpdlQueueBuffers aResponse); async DispatchCommands(Shmem commands, uint64_t size);
// -
sync GetFrontBufferSnapshot() returns (FrontBufferSnapshotIpc ret);
sync ReadPixels(ReadPixelsDesc desc, uint64_t maxBytes) returns (ReadPixelsResultIpc ret);
// -
sync CheckFramebufferStatus(uint32_t target) returns (uint32_t ret);
sync ClientWaitSync(uint64_t id, uint32_t flags, uint64_t timeout) returns (uint32_t ret);
sync CreateOpaqueFramebuffer(uint64_t id, OpaqueFramebufferOptions options) returns (bool ret);
sync DrawingBufferSize() returns (uvec2 ret);
sync Finish();
sync GetBufferParameter(uint32_t target, uint32_t pname) returns (MaybeDouble ret);
sync GetBufferSubData(uint32_t target, uint64_t srcByteOffset, uint64_t byteSize) returns (Shmem ret);
sync GetCompileResult(uint64_t id) returns (CompileResult ret);
sync GetError() returns (uint32_t ret);
sync GetFragDataLocation(uint64_t id, string name) returns (int32_t ret);
sync GetFramebufferAttachmentParameter(uint64_t id,
uint32_t attachment,
uint32_t pname) returns (MaybeDouble ret);
sync GetFrontBuffer(uint64_t fb, bool vr) returns (MaybeSurfaceDescriptor ret);
sync GetIndexedParameter(uint32_t target, uint32_t index) returns (MaybeDouble ret);
sync GetInternalformatParameter(uint32_t target, uint32_t internalFormat, uint32_t pname) returns (Int32Vector? ret);
sync GetLinkResult(uint64_t id) returns (LinkResult ret);
sync GetNumber(uint32_t pname) returns (MaybeDouble ret);
sync GetQueryParameter(uint64_t id, uint32_t pname) returns (MaybeDouble ret);
sync GetRenderbufferParameter(uint64_t id, uint32_t pname) returns (MaybeDouble ret);
sync GetSamplerParameter(uint64_t id, uint32_t pname) returns (MaybeDouble ret);
sync GetShaderPrecisionFormat(
uint32_t shaderType, uint32_t precisionType) returns (MaybeShaderPrecisionFormat ret);
sync GetString(uint32_t pname) returns (MaybeString ret);
sync GetTexParameter(uint64_t id, uint32_t pname) returns (MaybeDouble ret);
sync GetUniform(uint64_t id, uint32_t loc) returns (GetUniformData ret);
sync GetVertexAttrib(uint32_t index, uint32_t pname) returns (MaybeDouble ret);
sync IsEnabled(uint32_t cap) returns (bool ret);
sync OnMemoryPressure();
sync ValidateProgram(uint64_t id) returns (bool ret);
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

View File

@@ -21,36 +21,30 @@
namespace mozilla { namespace mozilla {
namespace webgl { namespace webgl {
struct QueueStatus { enum class QueueStatus {
enum EStatus { // Operation was successful
// Operation was successful kSuccess,
kSuccess, // The operation failed because the queue isn't ready for it.
// The operation failed because the queue isn't ready for it. // Either the queue is too full for an insert or too empty for a remove.
// Either the queue is too full for an insert or too empty for a remove. // The operation may succeed if retried.
// The operation may succeed if retried. kNotReady,
kNotReady, // The operation required more room than the queue supports.
// The operation required more room than the queue supports. // It should not be retried -- it will always fail.
// It should not be retried -- it will always fail. kTooSmall,
kTooSmall, // The operation failed for some reason that is unrecoverable.
// The operation failed for some reason that is unrecoverable. // All values below this value indicate a fata error.
// All values below this value indicate a fata error. kFatalError,
kFatalError, // Fatal error: Internal processing ran out of memory. This is likely e.g.
// Fatal error: Internal processing ran out of memory. This is likely e.g. // during de-serialization.
// during de-serialization. kOOMError,
kOOMError,
} mValue;
MOZ_IMPLICIT QueueStatus(const EStatus status = kSuccess) : mValue(status) {}
explicit operator bool() const { return mValue == kSuccess; }
explicit operator int() const { return static_cast<int>(mValue); }
bool operator==(const EStatus& o) const { return mValue == o; }
bool operator!=(const EStatus& o) const { return !(*this == o); }
}; };
inline bool IsSuccess(QueueStatus status) { inline bool IsSuccess(QueueStatus status) {
return status == QueueStatus::kSuccess; return status == QueueStatus::kSuccess;
} }
inline bool operator!(const QueueStatus status) { return !IsSuccess(status); }
template <typename T> template <typename T>
struct RemoveCVR { struct RemoveCVR {
typedef typename std::remove_reference<typename std::remove_cv<T>::type>::type typedef typename std::remove_reference<typename std::remove_cv<T>::type>::type
@@ -84,35 +78,19 @@ struct IsTriviallySerializable
* goes for TryRemove, which fails when there isn't enough data in * goes for TryRemove, which fails when there isn't enough data in
* the queue yet for them to complete. * the queue yet for them to complete.
* *
* QueueParamTraits resolve this problem by allowing the Try... operations to
* use QueueParamTraits<typename RemoveCVR<Arg>::Type>::MinSize() to get a
* lower-bound on the amount of room in the queue required for Arg. If the
* operation needs more than is available then the operation quickly fails.
* Otherwise, (de)serialization will commence, although it may still fail if
* MinSize() was too low.
*
* Their expected interface is: * Their expected interface is:
* *
* template<> struct QueueParamTraits<typename RemoveCVR<Arg>::Type> { * template<> struct QueueParamTraits<typename RemoveCVR<Arg>::Type> {
* // Write data from aArg into the PCQ. It is an error to write less than * // Write data from aArg into the PCQ.
* // is reported by MinSize(aArg).
* static QueueStatus Write(ProducerView& aProducerView, const Arg& aArg) * static QueueStatus Write(ProducerView& aProducerView, const Arg& aArg)
* {...}; * {...};
* *
* // Read data from the PCQ into aArg, or just skip the data if aArg is null. * // Read data from the PCQ into aArg, or just skip the data if aArg is null.
* // It is an error to read less than is reported by MinSize(aArg).
* static QueueStatus Read(ConsumerView& aConsumerView, Arg* aArg) {...} * static QueueStatus Read(ConsumerView& aConsumerView, Arg* aArg) {...}
*
* // The minimum number of bytes needed to represent this object in the
* // queue. It is intended to be a very fast estimate but most cases can
* // easily compute the exact value.
* // It is an error for the queue to require less room than MinSize()
* // reports. A MinSize of 0 is always valid (albeit wasteful).
* static size_t MinSize(const Arg& aArg) {...}
* }; * };
*/ */
template <typename Arg> template <typename Arg>
struct QueueParamTraits; struct QueueParamTraits; // Todo: s/QueueParamTraits/SizedParamTraits/
/** /**
* The marshaller handles all data insertion into the queue. * The marshaller handles all data insertion into the queue.
@@ -182,15 +160,12 @@ class ProducerView {
* Copy bytes from aBuffer to the producer if there is enough room. * Copy bytes from aBuffer to the producer if there is enough room.
* aBufferSize must not be 0. * aBufferSize must not be 0.
*/ */
inline QueueStatus Write(const void* aBuffer, size_t aBufferSize); inline QueueStatus Write(const uint8_t* begin, const uint8_t* end);
/**
* Copy bytes from src (an array of Ts), to the producer if there is
* enough room. count is the number of elements in the array.
*/
template <typename T> template <typename T>
inline QueueStatus Write(const T* src, size_t count) { inline QueueStatus Write(const T* begin, const T* end) {
return Write(reinterpret_cast<const void*>(src), count * sizeof(T)); return Write(reinterpret_cast<const uint8_t*>(begin),
reinterpret_cast<const uint8_t*>(end));
} }
/** /**
@@ -202,17 +177,6 @@ class ProducerView {
typename RemoveCVR<Arg>::Type>::Write(*this, aArg); typename RemoveCVR<Arg>::Type>::Write(*this, aArg);
} }
/**
* MinSize of Arg using QueueParamTraits.
*/
template <typename Arg>
size_t MinSizeParam(const Arg& aArg = nullptr) {
return mozilla::webgl::QueueParamTraits<
typename RemoveCVR<Arg>::Type>::MinSize(*this, aArg);
}
inline size_t MinSizeBytes(size_t aNBytes);
QueueStatus GetStatus() { return mStatus; } QueueStatus GetStatus() { return mStatus; }
private: private:
@@ -241,16 +205,12 @@ class ConsumerView {
* Read bytes from the consumer if there is enough data. aBuffer may * Read bytes from the consumer if there is enough data. aBuffer may
* be null (in which case the data is skipped) * be null (in which case the data is skipped)
*/ */
inline QueueStatus Read(void* aBuffer, size_t aBufferSize); inline QueueStatus Read(uint8_t* begin, uint8_t* end);
/**
* Read bytes from the consumer into an array of Ts, if there is enough data.
* aBuffer may be null (in which case the data is skipped). count is the
* number of array elements to read.
*/
template <typename T> template <typename T>
inline QueueStatus Read(T* dest, size_t count) { inline QueueStatus Read(T* begin, T* end) {
return Read(reinterpret_cast<void*>(dest), count * sizeof(T)); return Read(reinterpret_cast<uint8_t*>(begin),
reinterpret_cast<uint8_t*>(end));
} }
/** /**
@@ -260,22 +220,10 @@ class ConsumerView {
template <typename Arg> template <typename Arg>
QueueStatus ReadParam(Arg* aArg) { QueueStatus ReadParam(Arg* aArg) {
MOZ_ASSERT(aArg); MOZ_ASSERT(aArg);
return mozilla::webgl::QueueParamTraits<std::remove_cv_t<Arg>*>::Read(*this, return mozilla::webgl::QueueParamTraits<std::remove_cv_t<Arg>>::Read(*this,
aArg); aArg);
} }
/**
* MinSize of Arg using QueueParamTraits. aArg may be null.
*/
template <typename Arg>
size_t MinSizeParam(Arg& aArg) {
MOZ_ASSERT(aArg);
return mozilla::webgl::QueueParamTraits<std::remove_cv_t<Arg>&>::MinSize(
*this, aArg);
}
inline size_t MinSizeBytes(size_t aNBytes);
QueueStatus GetStatus() { return mStatus; } QueueStatus GetStatus() { return mStatus; }
private: private:
@@ -286,60 +234,22 @@ class ConsumerView {
}; };
template <typename T> template <typename T>
QueueStatus ProducerView<T>::Write(const void* aBuffer, size_t aBufferSize) { QueueStatus ProducerView<T>::Write(const uint8_t* begin, const uint8_t* end) {
MOZ_ASSERT(aBuffer && (aBufferSize > 0)); MOZ_ASSERT(begin);
if (!mStatus) { MOZ_ASSERT(begin < end);
return mStatus; if (IsSuccess(mStatus)) {
mStatus = mProducer->WriteObject(mRead, mWrite, begin, end - begin);
} }
return mStatus;
if (mProducer->NeedsSharedMemory(aBufferSize)) {
mozilla::ipc::Shmem shmem;
QueueStatus status = mProducer->AllocShmem(&shmem, aBufferSize, aBuffer);
if (!IsSuccess(status)) {
return status;
}
return WriteParam(std::move(shmem));
}
return mProducer->WriteObject(mRead, mWrite, aBuffer, aBufferSize);
} }
template <typename T> template <typename T>
size_t ProducerView<T>::MinSizeBytes(size_t aNBytes) { QueueStatus ConsumerView<T>::Read(uint8_t* begin, uint8_t* end) {
mozilla::ipc::Shmem shmem; MOZ_ASSERT(begin < end);
return mProducer->NeedsSharedMemory(aNBytes) ? MinSizeParam(shmem) : aNBytes; if (IsSuccess(mStatus)) {
} mStatus = mConsumer->ReadObject(mRead, mWrite, begin, end - begin);
template <typename T>
QueueStatus ConsumerView<T>::Read(void* aBuffer, size_t aBufferSize) {
MOZ_ASSERT(aBufferSize > 0);
if (!mStatus) {
return mStatus;
} }
return mStatus;
if (mConsumer->NeedsSharedMemory(aBufferSize)) {
mozilla::ipc::Shmem shmem;
QueueStatus status = ReadParam(&shmem);
if (!IsSuccess(status)) {
return status;
}
if ((shmem.Size<uint8_t>() != aBufferSize) || (!shmem.get<uint8_t>())) {
return QueueStatus::kFatalError;
}
if (aBuffer) {
memcpy(aBuffer, shmem.get<uint8_t>(), aBufferSize);
}
return QueueStatus::kSuccess;
}
return mConsumer->ReadObject(mRead, mWrite, aBuffer, aBufferSize);
}
template <typename T>
size_t ConsumerView<T>::MinSizeBytes(size_t aNBytes) {
mozilla::ipc::Shmem shmem;
return mConsumer->NeedsSharedMemory(aNBytes) ? MinSizeParam(shmem) : aNBytes;
} }
// --------------------------------------------------------------- // ---------------------------------------------------------------
@@ -355,7 +265,8 @@ struct QueueParamTraits {
"No QueueParamTraits specialization was found for this type " "No QueueParamTraits specialization was found for this type "
"and it does not satisfy IsTriviallySerializable."); "and it does not satisfy IsTriviallySerializable.");
// Write self as binary // Write self as binary
return aProducerView.Write(&aArg, sizeof(Arg)); const auto begin = &aArg;
return aProducerView.Write(begin, begin + 1);
} }
template <typename U> template <typename U>
@@ -364,15 +275,7 @@ struct QueueParamTraits {
"No QueueParamTraits specialization was found for this type " "No QueueParamTraits specialization was found for this type "
"and it does not satisfy IsTriviallySerializable."); "and it does not satisfy IsTriviallySerializable.");
// Read self as binary // Read self as binary
return aConsumerView.Read(aArg, sizeof(Arg)); return aConsumerView.Read(aArg, aArg + 1);
}
template <typename View>
static constexpr size_t MinSize(View& aView, const Arg& aArg) {
static_assert(mozilla::webgl::template IsTriviallySerializable<Arg>::value,
"No QueueParamTraits specialization was found for this type "
"and it does not satisfy IsTriviallySerializable.");
return sizeof(Arg);
} }
}; };
@@ -387,9 +290,9 @@ struct EnumSerializer {
typedef typename std::underlying_type<E>::type DataType; typedef typename std::underlying_type<E>::type DataType;
template <typename U> template <typename U>
static void Write(ProducerView<U>& aProducerView, const ParamType& aValue) { static auto Write(ProducerView<U>& aProducerView, const ParamType& aValue) {
MOZ_RELEASE_ASSERT(EnumValidator::IsLegalValue(aValue)); MOZ_RELEASE_ASSERT(EnumValidator::IsLegalValue(aValue));
aProducerView.WriteParam(DataType(aValue)); return aProducerView.WriteParam(DataType(aValue));
} }
template <typename U> template <typename U>
@@ -398,21 +301,16 @@ struct EnumSerializer {
if (!aConsumerView.ReadParam(&value)) { if (!aConsumerView.ReadParam(&value)) {
CrashReporter::AnnotateCrashReport( CrashReporter::AnnotateCrashReport(
CrashReporter::Annotation::IPCReadErrorReason, "Bad iter"_ns); CrashReporter::Annotation::IPCReadErrorReason, "Bad iter"_ns);
return aConsumerView.GetStatus(); return IsSuccess(aConsumerView.GetStatus());
} }
if (!EnumValidator::IsLegalValue(ParamType(value))) { if (!EnumValidator::IsLegalValue(ParamType(value))) {
CrashReporter::AnnotateCrashReport( CrashReporter::AnnotateCrashReport(
CrashReporter::Annotation::IPCReadErrorReason, "Illegal value"_ns); CrashReporter::Annotation::IPCReadErrorReason, "Illegal value"_ns);
return aConsumerView.GetStatus(); return IsSuccess(aConsumerView.GetStatus());
} }
*aResult = ParamType(value); *aResult = ParamType(value);
return QueueStatus::kSuccess; return true;
}
template <typename View>
static constexpr size_t MinSize(View& aView, const ParamType& aArg) {
return aView.MinSizeParam(DataType(aArg));
} }
}; };
@@ -432,31 +330,9 @@ struct ContiguousEnumSerializerInclusive
// --------------------------------------------------------------- // ---------------------------------------------------------------
template <> template <>
struct QueueParamTraits<QueueStatus::EStatus> struct QueueParamTraits<QueueStatus>
: public ContiguousEnumSerializerInclusive< : public ContiguousEnumSerializerInclusive<
QueueStatus::EStatus, QueueStatus::EStatus::kSuccess, QueueStatus, QueueStatus::kSuccess, QueueStatus::kOOMError> {};
QueueStatus::EStatus::kOOMError> {};
template <>
struct QueueParamTraits<QueueStatus> {
using ParamType = QueueStatus;
template <typename U>
static QueueStatus Write(ProducerView<U>& aProducerView,
const ParamType& aArg) {
return aProducerView.WriteParam(aArg.mValue);
}
template <typename U>
static QueueStatus Read(ConsumerView<U>& aConsumerView, ParamType* aArg) {
return aConsumerView.ReadParam(&aArg->mValue);
}
template <typename View>
static size_t MinSize(View& aView, const ParamType& aArg) {
return aView.MinSize(aArg.mValue);
}
};
// --------------------------------------------------------------- // ---------------------------------------------------------------
@@ -482,7 +358,7 @@ struct QueueParamTraits<nsACString> {
template <typename U> template <typename U>
static QueueStatus Read(ConsumerView<U>& aConsumerView, ParamType* aArg) { static QueueStatus Read(ConsumerView<U>& aConsumerView, ParamType* aArg) {
bool isVoid = false; bool isVoid = false;
if (!aConsumerView.ReadParam(&isVoid)) { if (!IsSuccess(aConsumerView.ReadParam(&isVoid))) {
return aConsumerView.GetStatus(); return aConsumerView.GetStatus();
} }
aArg->SetIsVoid(isVoid); aArg->SetIsVoid(isVoid);
@@ -491,7 +367,7 @@ struct QueueParamTraits<nsACString> {
} }
uint32_t len = 0; uint32_t len = 0;
if (!aConsumerView.ReadParam(&len)) { if (!IsSuccess(aConsumerView.ReadParam(&len))) {
return aConsumerView.GetStatus(); return aConsumerView.GetStatus();
} }
@@ -504,24 +380,13 @@ struct QueueParamTraits<nsACString> {
if (!buf) { if (!buf) {
return QueueStatus::kOOMError; return QueueStatus::kOOMError;
} }
if (!aConsumerView.Read(buf, len)) { if (!IsSuccess(aConsumerView.Read(buf, len))) {
return aConsumerView.GetStatus(); return aConsumerView.GetStatus();
} }
buf[len] = '\0'; buf[len] = '\0';
aArg->Adopt(buf, len); aArg->Adopt(buf, len);
return QueueStatus::kSuccess; return QueueStatus::kSuccess;
} }
template <typename View>
static size_t MinSize(View& aView, const ParamType& aArg) {
size_t minSize = aView.template MinSizeParam<bool>(aArg.IsVoid());
if (aArg.IsVoid()) {
return minSize;
}
minSize += aView.template MinSizeParam<uint32_t>(aArg.Length()) +
aView.MinSizeBytes(aArg.Length());
return minSize;
}
}; };
template <> template <>
@@ -581,18 +446,6 @@ struct QueueParamTraits<nsAString> {
aArg->Adopt(buf, len); aArg->Adopt(buf, len);
return QueueStatus::kSuccess; return QueueStatus::kSuccess;
} }
template <typename View>
static size_t MinSize(View& aView, const ParamType& aArg) {
size_t minSize = aView.template MinSizeParam<bool>(aArg.IsVoid());
if (aArg.IsVoid()) {
return minSize;
}
uint32_t sizeofchar = sizeof(typename ParamType::char_type);
minSize += aView.template MinSizeParam<uint32_t>(aArg.Length()) +
aView.MinSizeBytes(aArg.Length() * sizeofchar);
return minSize;
}
}; };
template <> template <>
@@ -645,15 +498,6 @@ struct NSArrayQueueParamTraits<nsTArray<_ElementType>, false> {
} }
return aConsumerView.GetStatus(); return aConsumerView.GetStatus();
} }
template <typename View>
static size_t MinSize(View& aView, const ParamType& aArg) {
size_t ret = aView.MinSizeParam(aArg.Length());
for (auto& elt : aArg) {
ret += aView.MinSizeParam(elt);
}
return ret;
}
}; };
// For ElementTypes that are IsTriviallySerializable // For ElementTypes that are IsTriviallySerializable
@@ -684,13 +528,6 @@ struct NSArrayQueueParamTraits<nsTArray<_ElementType>, true> {
return aConsumerView.Read(aArg->Elements(), arrayLen * sizeof(ElementType)); return aConsumerView.Read(aArg->Elements(), arrayLen * sizeof(ElementType));
} }
template <typename View>
static size_t MinSize(View& aView, const ParamType& aArg) {
size_t ret = aView.template MinSizeParam<size_t>(aArg.Length());
ret += aView.MinSizeBytes(aArg.Length() * sizeof(ElementType));
return ret;
}
}; };
template <typename ElementType> template <typename ElementType>
@@ -728,15 +565,6 @@ struct ArrayQueueParamTraits<Array<_ElementType, Length>, false> {
} }
return aConsumerView.GetStatus(); return aConsumerView.GetStatus();
} }
template <typename View>
static size_t MinSize(View& aView, const ParamType& aArg) {
size_t ret = 0;
for (const auto& elt : aArg) {
ret += aView.MinSizeParam(elt);
}
return ret;
}
}; };
// For ElementTypes that are IsTriviallySerializable // For ElementTypes that are IsTriviallySerializable
@@ -755,11 +583,6 @@ struct ArrayQueueParamTraits<Array<_ElementType, Length>, true> {
static QueueStatus Read(ConsumerView<U>& aConsumerView, ParamType* aArg) { static QueueStatus Read(ConsumerView<U>& aConsumerView, ParamType* aArg) {
return aConsumerView.Read(aArg->begin(), sizeof(ElementType[Length])); return aConsumerView.Read(aArg->begin(), sizeof(ElementType[Length]));
} }
template <typename View>
static size_t MinSize(View& aView, const ParamType& aArg) {
return aView.MinSizeBytes(sizeof(ElementType[Length]));
}
}; };
template <typename ElementType, size_t Length> template <typename ElementType, size_t Length>
@@ -797,12 +620,6 @@ struct QueueParamTraits<Maybe<ElementType>> {
aArg->emplace(); aArg->emplace();
return aConsumerView.ReadParam(aArg->ptr()); return aConsumerView.ReadParam(aArg->ptr());
} }
template <typename View>
static size_t MinSize(View& aView, const ParamType& aArg) {
return aView.template MinSizeParam<bool>(aArg) +
(aArg.isSome() ? aView.MinSizeParam(aArg.ref()) : 0);
}
}; };
// --------------------------------------------------------------- // ---------------------------------------------------------------
@@ -836,12 +653,6 @@ struct QueueParamTraits<Maybe<Variant<T, Ts...>>> {
aArg->emplace(VariantType<T>()); aArg->emplace(VariantType<T>());
return aConsumerView.ReadParam(aArg->ptr()); return aConsumerView.ReadParam(aArg->ptr());
} }
template <typename View>
static size_t MinSize(View& aView, const ParamType& aArg) {
return aView.MinSizeParam(aArg.mIsSome) +
(aArg.isSome() ? aView.MinSizeParam(aArg.ref()) : 0);
}
}; };
// --------------------------------------------------------------- // ---------------------------------------------------------------
@@ -862,11 +673,6 @@ struct QueueParamTraits<std::pair<TypeA, TypeB>> {
aConsumerView.ReadParam(aArg->first()); aConsumerView.ReadParam(aArg->first());
return aConsumerView.ReadParam(aArg->second()); return aConsumerView.ReadParam(aArg->second());
} }
template <typename View>
static size_t MinSize(View& aView, const ParamType& aArg) {
return aView.MinSizeParam(aArg.first()) + aView.MinSizeParam(aArg.second());
}
}; };
// --------------------------------------------------------------- // ---------------------------------------------------------------
@@ -905,105 +711,10 @@ struct QueueParamTraits<UniquePtr<T>> {
aArg->reset(obj); aArg->reset(obj);
return aConsumerView.ReadParam(obj); return aConsumerView.ReadParam(obj);
} }
template <typename View>
static size_t MinSize(View& aView, const ParamType& aArg) {
size_t ret = aView.template MinSizeParam<bool>(aArg);
return ret + aView.MinSizeParam(*aArg);
}
}; };
// --------------------------------------------------------------- // ---------------------------------------------------------------
// C++ does not allow this struct with a templated method to be local to
// another struct (QueueParamTraits<Variant<...>>) so we put it here.
template <typename U>
struct PcqVariantWriter {
ProducerView<U>& mView;
template <typename T>
QueueStatus match(const T& x) {
return mView.WriteParam(x);
}
};
template <typename... Types>
struct QueueParamTraits<Variant<Types...>> {
using ParamType = Variant<Types...>;
using Tag = typename mozilla::detail::VariantTag<Types...>::Type;
template <typename U>
static QueueStatus Write(ProducerView<U>& aProducerView,
const ParamType& aArg) {
aProducerView.WriteParam(aArg.tag);
return aArg.match(PcqVariantWriter{aProducerView});
}
// Check the N-1th tag. See ParamTraits<mozilla::Variant> for details.
template <size_t N, typename dummy = void>
struct VariantReader {
using Next = VariantReader<N - 1>;
template <typename U>
static QueueStatus Read(ConsumerView<U>& aView, Tag aTag, ParamType* aArg) {
if (aTag == N - 1) {
using EntryType = typename mozilla::detail::Nth<N - 1, Types...>::Type;
return aView.ReadParam(*static_cast<EntryType*>(aArg->ptr()));
}
return Next::Read(aView, aTag, aArg);
}
};
template <typename dummy>
struct VariantReader<0, dummy> {
template <typename U>
static QueueStatus Read(ConsumerView<U>& aView, Tag aTag, ParamType* aArg) {
MOZ_ASSERT_UNREACHABLE("Tag wasn't for an entry in this Variant");
return QueueStatus::kFatalError;
}
};
template <typename U>
static QueueStatus Read(ConsumerView<U>& aConsumerView, ParamType* aArg) {
Tag tag;
if (!aConsumerView.ReadParam(&tag)) {
return aConsumerView.GetStatus();
}
aArg->tag = tag;
return VariantReader<sizeof...(Types)>::Read(aConsumerView, tag, aArg);
}
// Get the min size of the given variant or get the min size of all of the
// variant's types.
template <size_t N, typename View>
struct MinSizeVariant {
using Next = MinSizeVariant<N - 1, View>;
static size_t MinSize(View& aView, const Tag* aTag, const ParamType& aArg) {
using EntryType = typename mozilla::detail::Nth<N - 1, Types...>::Type;
MOZ_ASSERT(aTag);
if (*aTag == N - 1) {
return aView.MinSizeParam(aArg.template as<EntryType>());
}
return Next::MinSize(aView, aTag, aArg);
}
};
template <typename View>
struct MinSizeVariant<0, View> {
// We've reached the end of the type list. We will legitimately get here
// when calculating MinSize for a null Variant.
static size_t MinSize(View& aView, const Tag* aTag, const ParamType& aArg) {
MOZ_ASSERT_UNREACHABLE("Tag wasn't for an entry in this Variant");
return 0;
}
};
template <typename View>
static size_t MinSize(View& aView, const ParamType& aArg) {
return aView.MinSizeParam(aArg.tag) +
MinSizeVariant<sizeof...(Types), View>::MinSize(aView, aArg.tag,
aArg);
}
};
template <> template <>
struct QueueParamTraits<mozilla::ipc::Shmem> { struct QueueParamTraits<mozilla::ipc::Shmem> {
using ParamType = mozilla::ipc::Shmem; using ParamType = mozilla::ipc::Shmem;
@@ -1036,12 +747,6 @@ struct QueueParamTraits<mozilla::ipc::Shmem> {
rawmem, id); rawmem, id);
return QueueStatus::kSuccess; return QueueStatus::kSuccess;
} }
template <typename View>
static size_t MinSize(View& aView, const ParamType& aArg) {
return aView.MinSizeParam(
aArg.Id(mozilla::ipc::Shmem::PrivateIPDLCaller()));
}
}; };
} // namespace webgl } // namespace webgl

View File

@@ -36,7 +36,7 @@ class WebGL2Context final : public WebGLContext {
void CopyBufferSubData(GLenum readTarget, GLenum writeTarget, void CopyBufferSubData(GLenum readTarget, GLenum writeTarget,
uint64_t readOffset, uint64_t writeOffset, uint64_t readOffset, uint64_t writeOffset,
uint64_t size) const; uint64_t size) const;
void GetBufferSubData(GLenum target, uint64_t srcByteOffset, bool GetBufferSubData(GLenum target, uint64_t srcByteOffset,
const Range<uint8_t>& dest) const; const Range<uint8_t>& dest) const;
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------

View File

@@ -78,23 +78,23 @@ void WebGL2Context::CopyBufferSubData(GLenum readTarget, GLenum writeTarget,
writeBuffer->ResetLastUpdateFenceId(); writeBuffer->ResetLastUpdateFenceId();
} }
void WebGL2Context::GetBufferSubData(GLenum target, uint64_t srcByteOffset, bool WebGL2Context::GetBufferSubData(GLenum target, uint64_t srcByteOffset,
const Range<uint8_t>& dest) const { const Range<uint8_t>& dest) const {
const FuncScope funcScope(*this, "getBufferSubData"); const FuncScope funcScope(*this, "getBufferSubData");
if (IsContextLost()) return; if (IsContextLost()) return false;
const auto& buffer = ValidateBufferSelection(target); const auto& buffer = ValidateBufferSelection(target);
if (!buffer) return; if (!buffer) return false;
const auto byteLen = dest.length(); const auto byteLen = dest.length();
if (!buffer->ValidateRange(srcByteOffset, byteLen)) return; if (!buffer->ValidateRange(srcByteOffset, byteLen)) return false;
//// ////
if (!CheckedInt<GLintptr>(srcByteOffset).isValid() || if (!CheckedInt<GLintptr>(srcByteOffset).isValid() ||
!CheckedInt<GLsizeiptr>(byteLen).isValid()) { !CheckedInt<GLsizeiptr>(byteLen).isValid()) {
ErrorOutOfMemory("offset or size too large for platform."); ErrorOutOfMemory("offset or size too large for platform.");
return; return false;
} }
const GLsizeiptr glByteLen(byteLen); const GLsizeiptr glByteLen(byteLen);
@@ -144,6 +144,7 @@ void WebGL2Context::GetBufferSubData(GLenum target, uint64_t srcByteOffset,
gl->fBindTransformFeedback(LOCAL_GL_TRANSFORM_FEEDBACK, tfo); gl->fBindTransformFeedback(LOCAL_GL_TRANSFORM_FEEDBACK, tfo);
} }
} }
return true;
} }
} // namespace mozilla } // namespace mozilla

View File

@@ -16,6 +16,45 @@ WebGLChild::WebGLChild(ClientWebGLContext& context)
WebGLChild::~WebGLChild() { (void)Send__delete__(this); } WebGLChild::~WebGLChild() { (void)Send__delete__(this); }
// -
Maybe<Range<uint8_t>> WebGLChild::AllocPendingCmdBytes(const size_t size) {
if (!mPendingCmds) {
mPendingCmds.reset(new webgl::ShmemCmdBuffer);
size_t capacity = 1000 * 1000;
if (capacity < size) {
capacity = size;
}
if (!PWebGLChild::AllocShmem(
capacity, mozilla::ipc::SharedMemory::SharedMemoryType::TYPE_BASIC,
&(mPendingCmds->mShmem))) {
return {};
}
}
auto remaining = mPendingCmds->Remaining();
if (size > remaining.length()) {
FlushPendingCmds();
return AllocPendingCmdBytes(size);
}
mPendingCmds->mPos += size;
return Some(Range<uint8_t>{remaining.begin(), remaining.begin() + size});
}
void WebGLChild::FlushPendingCmds() {
if (!mPendingCmds) return;
const auto cmdBytes = mPendingCmds->mPos;
SendDispatchCommands(std::move(mPendingCmds->mShmem), cmdBytes);
mPendingCmds = nullptr;
mFlushedCmdInfo.flushes += 1;
mFlushedCmdInfo.flushedCmdBytes += cmdBytes;
}
// -
mozilla::ipc::IPCResult WebGLChild::RecvJsWarning( mozilla::ipc::IPCResult WebGLChild::RecvJsWarning(
const std::string& text) const { const std::string& text) const {
mContext.JsWarning(text); mContext.JsWarning(text);

View File

@@ -27,11 +27,17 @@ class ClientWebGLContext;
namespace dom { namespace dom {
struct FlushedCmdInfo final {
size_t flushes = 0;
size_t flushedCmdBytes = 0;
};
class WebGLChild final : public PWebGLChild, class WebGLChild final : public PWebGLChild,
public SyncProducerActor<WebGLChild>,
public AsyncConsumerActor<WebGLChild>,
public SupportsWeakPtr<WebGLChild>, public SupportsWeakPtr<WebGLChild>,
public mozilla::webgl::PcqActor { public mozilla::webgl::PcqActor {
std::unique_ptr<webgl::ShmemCmdBuffer> mPendingCmds;
FlushedCmdInfo mFlushedCmdInfo;
public: public:
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(WebGLChild) MOZ_DECLARE_WEAKREFERENCE_TYPENAME(WebGLChild)
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebGLChild, override); NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebGLChild, override);
@@ -44,6 +50,9 @@ class WebGLChild final : public PWebGLChild,
// For SyncProducerActor: // For SyncProducerActor:
static IpdlQueueProtocol GetIpdlQueueProtocol(size_t aCmd, ...); static IpdlQueueProtocol GetIpdlQueueProtocol(size_t aCmd, ...);
Maybe<Range<uint8_t>> AllocPendingCmdBytes(size_t);
void FlushPendingCmds();
private: private:
friend PWebGLChild; friend PWebGLChild;
virtual ~WebGLChild(); virtual ~WebGLChild();

View File

@@ -6,10 +6,12 @@
#ifndef WEBGLCOMMANDQUEUE_H_ #ifndef WEBGLCOMMANDQUEUE_H_
#define WEBGLCOMMANDQUEUE_H_ #define WEBGLCOMMANDQUEUE_H_
#include <type_traits>
#include "mozilla/FunctionTypeTraits.h" #include "mozilla/FunctionTypeTraits.h"
#include "mozilla/dom/ProducerConsumerQueue.h" #include "mozilla/dom/ProducerConsumerQueue.h"
#include "mozilla/ipc/IPDLParamTraits.h" #include "mozilla/ipc/IPDLParamTraits.h"
#include <type_traits> #include "QueueParamTraits.h"
#include "WebGLTypes.h"
// Get around a bug in Clang related to __thiscall method pointers // Get around a bug in Clang related to __thiscall method pointers
#if defined(_M_IX86) #if defined(_M_IX86)
@@ -20,8 +22,135 @@
namespace mozilla { namespace mozilla {
using webgl::QueueStatus;
namespace webgl {
struct ShmemCmdBuffer final {
mozilla::ipc::Shmem mShmem = {};
size_t mPos = 0;
Range<uint8_t> Remaining() const {
const auto range = ByteRange(mShmem);
return {range.begin() + mPos, range.end()};
}
};
// -
class RangeConsumerView final : public webgl::ConsumerView<RangeConsumerView> {
RangedPtr<const uint8_t> mSrcItr;
const RangedPtr<const uint8_t> mSrcEnd;
public:
auto Remaining() const { return *MaybeAs<size_t>(mSrcEnd - mSrcItr); }
explicit RangeConsumerView(const Range<const uint8_t> range)
: ConsumerView(this, nullptr, 0),
mSrcItr(range.begin()),
mSrcEnd(range.end()) {
(void)Remaining(); // assert size non-negative
}
QueueStatus ReadObject(size_t*, size_t, void* const src, const size_t size) {
const auto remaining = Remaining();
if (size > remaining) return QueueStatus::kTooSmall;
memcpy(src, mSrcItr.get(), size);
mSrcItr += size;
return QueueStatus::kSuccess;
}
};
// -
namespace details {
class SizeOnlyProducerView final
: public webgl::ProducerView<SizeOnlyProducerView> {
size_t mRequiredSize = 0;
public:
SizeOnlyProducerView() : ProducerView(this, 0, nullptr) {}
QueueStatus WriteObject(size_t, size_t*, const void*, const size_t size) {
mRequiredSize += size;
return QueueStatus::kSuccess;
}
const auto& RequiredSize() const { return mRequiredSize; }
};
// -
class RangeProducerView final : public webgl::ProducerView<RangeProducerView> {
RangedPtr<uint8_t> mDestItr;
const RangedPtr<uint8_t> mDestEnd;
public:
auto Remaining() const { return *MaybeAs<size_t>(mDestEnd - mDestItr); }
explicit RangeProducerView(const Range<uint8_t> range)
: ProducerView(this, 0, nullptr),
mDestItr(range.begin()),
mDestEnd(range.end()) {
(void)Remaining(); // assert size non-negative
}
QueueStatus WriteObject(size_t, size_t*, const void* const src,
const size_t size) {
MOZ_ASSERT(size <= Remaining());
memcpy(mDestItr.get(), src, size);
mDestItr += size;
return QueueStatus::kSuccess;
}
};
// -
template <typename ProducerViewT>
inline void Serialize(ProducerViewT&) {}
template <typename ProducerViewT, typename Arg, typename... Args>
inline void Serialize(ProducerViewT& view, const Arg& arg,
const Args&... args) {
MOZ_ALWAYS_TRUE(view.WriteParam(arg) == QueueStatus::kSuccess);
Serialize(view, args...);
}
} // namespace details
// -
template <typename... Args>
size_t SerializedSize(const Args&... args) {
webgl::details::SizeOnlyProducerView sizeView;
webgl::details::Serialize(sizeView, args...);
return sizeView.RequiredSize();
}
template <typename... Args>
void Serialize(Range<uint8_t> dest, const Args&... args) {
webgl::details::RangeProducerView view(dest);
webgl::details::Serialize(view, args...);
}
// -
inline bool Deserialize(RangeConsumerView& view) { return true; }
template <typename Arg, typename... Args>
inline bool Deserialize(RangeConsumerView& view, Arg& arg, Args&... args) {
if (!webgl::QueueParamTraits<Arg>::Read(view, &arg)) return false;
return Deserialize(view, args...);
}
} // namespace webgl
// -
using mozilla::ipc::IPDLParamTraits; using mozilla::ipc::IPDLParamTraits;
using mozilla::webgl::QueueStatus;
enum CommandResult { kSuccess, kTimeExpired, kQueueEmpty, kError }; enum CommandResult { kSuccess, kTimeExpired, kQueueEmpty, kError };
@@ -528,41 +657,62 @@ class SyncCommandSink : public CommandSink<Command, _Sink> {
template <template <size_t> typename Derived> template <template <size_t> typename Derived>
class EmptyMethodDispatcher { class EmptyMethodDispatcher {
public: public:
template <typename SinkType, typename ObjectType> template <typename ObjectT>
static MOZ_ALWAYS_INLINE bool DispatchCommand(size_t aId, SinkType& aSink, static MOZ_ALWAYS_INLINE bool DispatchCommand(ObjectT&, const size_t,
ObjectType& aObj) { webgl::RangeConsumerView&) {
MOZ_CRASH("Illegal ID in DispatchCommand"); MOZ_CRASH("Illegal ID in DispatchCommand");
} }
static MOZ_ALWAYS_INLINE CommandSyncType SyncType(size_t aId) { static MOZ_ALWAYS_INLINE CommandSyncType SyncType(size_t) {
MOZ_CRASH("Illegal ID in SyncType"); MOZ_CRASH("Illegal ID in SyncType");
} }
}; };
// -
template <typename ReturnT, typename ObjectT, typename... Args>
std::tuple<std::remove_cv_t<std::remove_reference_t<Args>>...> ArgsTuple(
ReturnT (ObjectT::*)(Args... args)) {
return std::tuple<std::remove_cv_t<std::remove_reference_t<Args>>...>{};
}
template <typename ReturnT, typename ObjectT, typename... Args>
std::tuple<std::remove_cv_t<std::remove_reference_t<Args>>...> ArgsTuple(
ReturnT (ObjectT::*)(Args... args) const) {
return std::tuple<std::remove_cv_t<std::remove_reference_t<Args>>...>{};
}
// Derived type must be parameterized by the ID. // Derived type must be parameterized by the ID.
template <template <size_t> typename Derived, size_t id, typename MethodType, template <template <size_t> typename Derived, size_t ID, typename MethodType,
MethodType method, CommandSyncType syncType> MethodType method, CommandSyncType syncType>
class MethodDispatcher { class MethodDispatcher {
using DerivedType = Derived<id>; static constexpr size_t kId = ID;
using NextDispatcher = Derived<id + 1>; using DerivedType = Derived<ID>;
using NextDispatcher = Derived<ID + 1>;
public: public:
template <typename SinkType, typename ObjectType> template <typename ObjectT>
static MOZ_ALWAYS_INLINE bool DispatchCommand(size_t aId, SinkType& aSink, static MOZ_ALWAYS_INLINE bool DispatchCommand(
ObjectType& aObj) { ObjectT& obj, const size_t id, webgl::RangeConsumerView& view) {
if (aId == id) { if (id == kId) {
return (syncType == CommandSyncType::ASYNC) auto argsTuple = ArgsTuple(method);
? aSink.DispatchAsyncMethod(aObj, Method())
: aSink.DispatchSyncMethod(aObj, Method()); return std::apply(
[&](auto&... args) {
if (!webgl::Deserialize(view, args...)) return false;
(obj.*method)(args...);
return true;
},
argsTuple);
} }
return NextDispatcher::DispatchCommand(aId, aSink, aObj); return Derived<kId + 1>::DispatchCommand(obj, id, view);
} }
static MOZ_ALWAYS_INLINE CommandSyncType SyncType(size_t aId) { static MOZ_ALWAYS_INLINE CommandSyncType SyncType(size_t aId) {
return (aId == id) ? syncType : NextDispatcher::SyncType(aId); return (aId == kId) ? syncType : NextDispatcher::SyncType(kId);
} }
static constexpr CommandSyncType SyncType() { return syncType; } static constexpr CommandSyncType SyncType() { return syncType; }
static constexpr size_t Id() { return id; } static constexpr size_t Id() { return kId; }
static constexpr MethodType Method() { return method; } static constexpr MethodType Method() { return method; }
}; };

View File

@@ -1029,9 +1029,9 @@ Maybe<layers::SurfaceDescriptor> WebGLContext::GetFrontBuffer(
return front->ToSurfaceDescriptor(); return front->ToSurfaceDescriptor();
} }
RefPtr<gfx::DataSourceSurface> WebGLContext::GetFrontBufferSnapshot() { bool WebGLContext::FrontBufferSnapshotInto(Range<uint8_t> dest) {
const auto& front = mSwapChain.FrontBuffer(); const auto& front = mSwapChain.FrontBuffer();
if (!front) return nullptr; if (!front) return false;
// - // -
@@ -1076,32 +1076,13 @@ RefPtr<gfx::DataSourceSurface> WebGLContext::GetFrontBufferSnapshot() {
}); });
const auto& size = front->mDesc.size; const auto& size = front->mDesc.size;
const auto surfFormat = mOptions.alpha ? gfx::SurfaceFormat::B8G8R8A8 const size_t stride = size.width * 4;
: gfx::SurfaceFormat::B8G8R8X8; MOZ_ASSERT(dest.length() == stride * size.height);
const auto stride = size.width * 4; gl->fReadPixels(0, 0, size.width, size.height, LOCAL_GL_RGBA,
RefPtr<gfx::DataSourceSurface> surf = LOCAL_GL_UNSIGNED_BYTE, dest.begin().get());
gfx::Factory::CreateDataSourceSurfaceWithStride(size, surfFormat, stride, gfxUtils::ConvertBGRAtoRGBA(dest.begin().get(), stride * size.height);
/*zero=*/true);
MOZ_ASSERT(surf);
if (NS_WARN_IF(!surf)) return nullptr;
// - return true;
{
const gfx::DataSourceSurface::ScopedMap map(
surf, gfx::DataSourceSurface::READ_WRITE);
if (!map.IsMapped()) {
MOZ_ASSERT(false);
return nullptr;
}
MOZ_ASSERT(map.GetStride() == stride);
gl->fReadPixels(0, 0, size.width, size.height, LOCAL_GL_RGBA,
LOCAL_GL_UNSIGNED_BYTE, map.GetData());
gfxUtils::ConvertBGRAtoRGBA(map.GetData(), stride * size.height);
}
return surf;
} }
void WebGLContext::ClearVRSwapChain() { mWebVRSwapChain.ClearPool(); } void WebGLContext::ClearVRSwapChain() { mWebVRSwapChain.ClearPool(); }
@@ -1212,6 +1193,7 @@ void WebGLContext::LoseContext(const webgl::ContextLossReason reason) {
printf_stderr("WebGL(%p)::LoseContext(%u)\n", this, printf_stderr("WebGL(%p)::LoseContext(%u)\n", this,
static_cast<uint32_t>(reason)); static_cast<uint32_t>(reason));
mIsContextLost = true; mIsContextLost = true;
mLruPosition = {};
mHost->OnContextLoss(reason); mHost->OnContextLoss(reason);
} }
@@ -2079,6 +2061,10 @@ webgl::LinkActiveInfo GetLinkActiveInfo(
return ret; return ret;
} }
nsCString ToCString(const std::string& s) {
return nsCString(s.data(), s.size());
}
webgl::CompileResult WebGLContext::GetCompileResult( webgl::CompileResult WebGLContext::GetCompileResult(
const WebGLShader& shader) const { const WebGLShader& shader) const {
webgl::CompileResult ret; webgl::CompileResult ret;
@@ -2087,11 +2073,12 @@ webgl::CompileResult WebGLContext::GetCompileResult(
const auto& info = shader.CompileResults(); const auto& info = shader.CompileResults();
if (!info) return; if (!info) return;
if (!info->mValid) { if (!info->mValid) {
ret.log = info->mInfoLog; ret.log = info->mInfoLog.c_str();
return; return;
} }
ret.translatedSource = info->mObjectCode; // TODO: These could be large and should be made fallible.
ret.log = shader.CompileLog(); ret.translatedSource = ToCString(info->mObjectCode);
ret.log = ToCString(shader.CompileLog());
if (!shader.IsCompiled()) return; if (!shader.IsCompiled()) return;
ret.success = true; ret.success = true;
}(); }();
@@ -2102,7 +2089,7 @@ webgl::LinkResult WebGLContext::GetLinkResult(const WebGLProgram& prog) const {
webgl::LinkResult ret; webgl::LinkResult ret;
[&]() { [&]() {
ret.pending = false; // Link status polling not yet implemented. ret.pending = false; // Link status polling not yet implemented.
ret.log = prog.LinkLog(); ret.log = ToCString(prog.LinkLog());
const auto& info = prog.LinkInfo(); const auto& info = prog.LinkInfo();
if (!info) return; if (!info) return;
ret.success = true; ret.success = true;

View File

@@ -265,6 +265,7 @@ class WebGLContext : public VRefCounted, public SupportsWeakPtr<WebGLContext> {
LruPosition& operator=(LruPosition&& rhs) { LruPosition& operator=(LruPosition&& rhs) {
reset(); reset();
std::swap(mItr, rhs.mItr); std::swap(mItr, rhs.mItr);
rhs.reset();
return *this; return *this;
} }
@@ -491,10 +492,12 @@ class WebGLContext : public VRefCounted, public SupportsWeakPtr<WebGLContext> {
public: public:
void Present(WebGLFramebuffer*, layers::TextureType, const bool webvr); void Present(WebGLFramebuffer*, layers::TextureType, const bool webvr);
RefPtr<gfx::DataSourceSurface> GetFrontBufferSnapshot(); RefPtr<gfx::DataSourceSurface> GetFrontBufferSnapshot();
bool FrontBufferSnapshotInto(Range<uint8_t>);
Maybe<layers::SurfaceDescriptor> GetFrontBuffer(WebGLFramebuffer*, Maybe<layers::SurfaceDescriptor> GetFrontBuffer(WebGLFramebuffer*,
const bool webvr); const bool webvr);
void ClearVRSwapChain(); void ClearVRSwapChain();
void RunContextLossTimer(); void RunContextLossTimer();
void CheckForContextLoss(); void CheckForContextLoss();
@@ -599,15 +602,16 @@ class WebGLContext : public VRefCounted, public SupportsWeakPtr<WebGLContext> {
const webgl::FormatUsageInfo* usage) const; const webgl::FormatUsageInfo* usage) const;
protected: protected:
void ReadPixelsImpl(const webgl::ReadPixelsDesc&, uintptr_t data, webgl::ReadPixelsResult ReadPixelsImpl(const webgl::ReadPixelsDesc&,
uint64_t dataLen); uintptr_t dest, uint64_t availBytes);
bool DoReadPixelsAndConvert(const webgl::FormatInfo* srcFormat, bool DoReadPixelsAndConvert(const webgl::FormatInfo* srcFormat,
const webgl::ReadPixelsDesc&, uintptr_t dest, const webgl::ReadPixelsDesc&, uintptr_t dest,
uint64_t dataLen, uint32_t rowStride); uint64_t dataLen, uint32_t rowStride);
public: public:
void ReadPixelsPbo(const webgl::ReadPixelsDesc&, uint64_t offset); void ReadPixelsPbo(const webgl::ReadPixelsDesc&, uint64_t offset);
void ReadPixels(const webgl::ReadPixelsDesc&, const Range<uint8_t>& dest); webgl::ReadPixelsResult ReadPixelsInto(const webgl::ReadPixelsDesc&,
const Range<uint8_t>& dest);
//// ////

View File

@@ -920,18 +920,18 @@ static bool ValidatePackSize(const WebGLContext& webgl,
return true; return true;
} }
void WebGLContext::ReadPixels(const webgl::ReadPixelsDesc& desc, webgl::ReadPixelsResult WebGLContext::ReadPixelsInto(
const Range<uint8_t>& dest) { const webgl::ReadPixelsDesc& desc, const Range<uint8_t>& dest) {
const FuncScope funcScope(*this, "readPixels"); const FuncScope funcScope(*this, "readPixels");
if (IsContextLost()) return; if (IsContextLost()) return {};
if (mBoundPixelPackBuffer) { if (mBoundPixelPackBuffer) {
ErrorInvalidOperation("PIXEL_PACK_BUFFER must be null."); ErrorInvalidOperation("PIXEL_PACK_BUFFER must be null.");
return; return {};
} }
ReadPixelsImpl(desc, reinterpret_cast<uintptr_t>(dest.begin().get()), return ReadPixelsImpl(desc, reinterpret_cast<uintptr_t>(dest.begin().get()),
dest.length()); dest.length());
} }
void WebGLContext::ReadPixelsPbo(const webgl::ReadPixelsDesc& desc, void WebGLContext::ReadPixelsPbo(const webgl::ReadPixelsDesc& desc,
@@ -1077,22 +1077,22 @@ static bool ValidateReadPixelsFormatAndType(
return false; return false;
} }
void WebGLContext::ReadPixelsImpl(const webgl::ReadPixelsDesc& desc, webgl::ReadPixelsResult WebGLContext::ReadPixelsImpl(
const uintptr_t dest, const webgl::ReadPixelsDesc& desc, const uintptr_t dest,
const uint64_t availBytes) { const uint64_t availBytes) {
const webgl::FormatUsageInfo* srcFormat; const webgl::FormatUsageInfo* srcFormat;
uint32_t srcWidth; uint32_t srcWidth;
uint32_t srcHeight; uint32_t srcHeight;
if (!BindCurFBForColorRead(&srcFormat, &srcWidth, &srcHeight)) return; if (!BindCurFBForColorRead(&srcFormat, &srcWidth, &srcHeight)) return {};
////// //////
if (!ValidateReadPixelsFormatAndType(srcFormat, desc.pi, gl, this)) return; if (!ValidateReadPixelsFormatAndType(srcFormat, desc.pi, gl, this)) return {};
uint8_t bytesPerPixel; uint8_t bytesPerPixel;
if (!webgl::GetBytesPerPixel(desc.pi, &bytesPerPixel)) { if (!webgl::GetBytesPerPixel(desc.pi, &bytesPerPixel)) {
ErrorInvalidOperation("Unsupported format and type."); ErrorInvalidOperation("Unsupported format and type.");
return; return {};
} }
////// //////
@@ -1102,7 +1102,7 @@ void WebGLContext::ReadPixelsImpl(const webgl::ReadPixelsDesc& desc,
if (!ivec2::From(size)) { if (!ivec2::From(size)) {
ErrorInvalidValue("width and height must be non-negative."); ErrorInvalidValue("width and height must be non-negative.");
return; return {};
} }
const auto& packing = desc.packState; const auto& packing = desc.packState;
@@ -1110,11 +1110,11 @@ void WebGLContext::ReadPixelsImpl(const webgl::ReadPixelsDesc& desc,
uint32_t bytesNeeded; uint32_t bytesNeeded;
if (!ValidatePackSize(*this, packing, size, bytesPerPixel, &rowStride, if (!ValidatePackSize(*this, packing, size, bytesPerPixel, &rowStride,
&bytesNeeded)) &bytesNeeded))
return; return {};
if (bytesNeeded > availBytes) { if (bytesNeeded > availBytes) {
ErrorInvalidOperation("buffer too small"); ErrorInvalidOperation("buffer too small");
return; return {};
} }
//// ////
@@ -1125,7 +1125,7 @@ void WebGLContext::ReadPixelsImpl(const webgl::ReadPixelsDesc& desc,
if (!Intersect(srcWidth, srcOffset.x, size.x, &readX, &writeX, &rwWidth) || if (!Intersect(srcWidth, srcOffset.x, size.x, &readX, &writeX, &rwWidth) ||
!Intersect(srcHeight, srcOffset.y, size.y, &readY, &writeY, &rwHeight)) { !Intersect(srcHeight, srcOffset.y, size.y, &readY, &writeY, &rwHeight)) {
ErrorOutOfMemory("Bad subrect selection."); ErrorOutOfMemory("Bad subrect selection.");
return; return {};
} }
//////////////// ////////////////
@@ -1141,14 +1141,17 @@ void WebGLContext::ReadPixelsImpl(const webgl::ReadPixelsDesc& desc,
if (!rwWidth || !rwHeight) { if (!rwWidth || !rwHeight) {
// Disjoint rects, so we're done already. // Disjoint rects, so we're done already.
DummyReadFramebufferOperation(); DummyReadFramebufferOperation();
return; return {};
} }
const auto rwSize = *uvec2::From(rwWidth, rwHeight); const auto rwSize = *uvec2::From(rwWidth, rwHeight);
const auto res = webgl::ReadPixelsResult{
{{writeX, writeY}, {rwSize.x, rwSize.y}}, rowStride};
if (rwSize == size) { if (rwSize == size) {
DoReadPixelsAndConvert(srcFormat->format, desc, dest, bytesNeeded, DoReadPixelsAndConvert(srcFormat->format, desc, dest, bytesNeeded,
rowStride); rowStride);
return; return res;
} }
// Read request contains out-of-bounds pixels. Unfortunately: // Read request contains out-of-bounds pixels. Unfortunately:
@@ -1195,6 +1198,8 @@ void WebGLContext::ReadPixelsImpl(const webgl::ReadPixelsDesc& desc,
row += rowStride; row += rowStride;
} }
} }
return res;
} }
void WebGLContext::RenderbufferStorageMultisample(WebGLRenderbuffer& rb, void WebGLContext::RenderbufferStorageMultisample(WebGLRenderbuffer& rb,

View File

@@ -6,8 +6,55 @@
#ifndef WEBGLIPDL_H_ #ifndef WEBGLIPDL_H_
#define WEBGLIPDL_H_ #define WEBGLIPDL_H_
#include "mozilla/layers/LayersSurfaces.h"
#include "WebGLTypes.h" #include "WebGLTypes.h"
namespace mozilla {
namespace ipc {
template <>
struct IPDLParamTraits<mozilla::webgl::FrontBufferSnapshotIpc> final {
using T = mozilla::webgl::FrontBufferSnapshotIpc;
static void Write(IPC::Message* const msg, IProtocol* actor, T& in) {
WriteParam(msg, in.surfSize);
WriteIPDLParam(msg, actor, std::move(in.shmem));
}
static bool Read(const IPC::Message* const msg, PickleIterator* const itr,
IProtocol* actor, T* const out) {
return ReadParam(msg, itr, &out->surfSize) &&
ReadIPDLParam(msg, itr, actor, &out->shmem);
}
};
// -
template <>
struct IPDLParamTraits<mozilla::webgl::ReadPixelsResultIpc> final {
using T = mozilla::webgl::ReadPixelsResultIpc;
static void Write(IPC::Message* const msg, IProtocol* actor, T& in) {
WriteParam(msg, in.subrect);
WriteParam(msg, in.byteStride);
WriteIPDLParam(msg, actor, std::move(in.shmem));
}
static bool Read(const IPC::Message* const msg, PickleIterator* const itr,
IProtocol* actor, T* const out) {
return ReadParam(msg, itr, &out->subrect) &&
ReadParam(msg, itr, &out->byteStride) &&
ReadIPDLParam(msg, itr, actor, &out->shmem);
}
};
} // namespace ipc
namespace webgl {
using Int32Vector = std::vector<int32_t>;
} // namespace webgl
} // namespace mozilla
namespace IPC { namespace IPC {
template <> template <>
@@ -17,6 +64,13 @@ struct ParamTraits<mozilla::webgl::ContextLossReason>
mozilla::webgl::ContextLossReason::None, mozilla::webgl::ContextLossReason::None,
mozilla::webgl::ContextLossReason::Guilty> {}; mozilla::webgl::ContextLossReason::Guilty> {};
template <>
struct ParamTraits<mozilla::webgl::AttribBaseType>
: public ContiguousEnumSerializerInclusive<
mozilla::webgl::AttribBaseType,
mozilla::webgl::AttribBaseType::Boolean,
mozilla::webgl::AttribBaseType::Uint> {};
// - // -
template <typename T> template <typename T>
@@ -104,6 +158,333 @@ template <>
struct ParamTraits<mozilla::webgl::Limits> final struct ParamTraits<mozilla::webgl::Limits> final
: public PlainOldDataSerializer<mozilla::webgl::Limits> {}; : public PlainOldDataSerializer<mozilla::webgl::Limits> {};
// -
template <>
struct ParamTraits<mozilla::webgl::ReadPixelsDesc> final {
using T = mozilla::webgl::ReadPixelsDesc;
static void Write(Message* const msg, const T& in) {
WriteParam(msg, in.srcOffset);
WriteParam(msg, in.size);
WriteParam(msg, in.pi);
WriteParam(msg, in.packState);
}
static bool Read(const Message* const msg, PickleIterator* const itr,
T* const out) {
return ReadParam(msg, itr, &out->srcOffset) &&
ReadParam(msg, itr, &out->size) && ReadParam(msg, itr, &out->pi) &&
ReadParam(msg, itr, &out->packState);
}
};
// -
template <>
struct ParamTraits<mozilla::webgl::PixelPackState> final {
using T = mozilla::webgl::PixelPackState;
static void Write(Message* const msg, const T& in) {
WriteParam(msg, in.alignment);
WriteParam(msg, in.rowLength);
WriteParam(msg, in.skipRows);
WriteParam(msg, in.skipPixels);
}
static bool Read(const Message* const msg, PickleIterator* const itr,
T* const out) {
return ReadParam(msg, itr, &out->alignment) &&
ReadParam(msg, itr, &out->rowLength) &&
ReadParam(msg, itr, &out->skipRows) &&
ReadParam(msg, itr, &out->skipPixels);
}
};
// -
template <>
struct ParamTraits<mozilla::webgl::PackingInfo> final {
using T = mozilla::webgl::PackingInfo;
static void Write(Message* const msg, const T& in) {
WriteParam(msg, in.format);
WriteParam(msg, in.type);
}
static bool Read(const Message* const msg, PickleIterator* const itr,
T* const out) {
return ReadParam(msg, itr, &out->format) && ReadParam(msg, itr, &out->type);
}
};
// -
template <>
struct ParamTraits<mozilla::webgl::CompileResult> final {
using T = mozilla::webgl::CompileResult;
static void Write(Message* const msg, const T& in) {
WriteParam(msg, in.pending);
WriteParam(msg, in.log);
WriteParam(msg, in.translatedSource);
WriteParam(msg, in.success);
}
static bool Read(const Message* const msg, PickleIterator* const itr,
T* const out) {
return ReadParam(msg, itr, &out->pending) &&
ReadParam(msg, itr, &out->log) &&
ReadParam(msg, itr, &out->translatedSource) &&
ReadParam(msg, itr, &out->success);
}
};
// -
template <>
struct ParamTraits<mozilla::webgl::LinkResult> final {
using T = mozilla::webgl::LinkResult;
static void Write(Message* const msg, const T& in) {
WriteParam(msg, in.pending);
WriteParam(msg, in.log);
WriteParam(msg, in.success);
WriteParam(msg, in.active);
WriteParam(msg, in.tfBufferMode);
}
static bool Read(const Message* const msg, PickleIterator* const itr,
T* const out) {
return ReadParam(msg, itr, &out->pending) &&
ReadParam(msg, itr, &out->log) &&
ReadParam(msg, itr, &out->success) &&
ReadParam(msg, itr, &out->active) &&
ReadParam(msg, itr, &out->tfBufferMode);
}
};
// -
template <>
struct ParamTraits<mozilla::webgl::LinkActiveInfo> final {
using T = mozilla::webgl::LinkActiveInfo;
static void Write(Message* const msg, const T& in) {
WriteParam(msg, in.activeAttribs);
WriteParam(msg, in.activeUniforms);
WriteParam(msg, in.activeUniformBlocks);
WriteParam(msg, in.activeTfVaryings);
}
static bool Read(const Message* const msg, PickleIterator* const itr,
T* const out) {
return ReadParam(msg, itr, &out->activeAttribs) &&
ReadParam(msg, itr, &out->activeUniforms) &&
ReadParam(msg, itr, &out->activeUniformBlocks) &&
ReadParam(msg, itr, &out->activeTfVaryings);
}
};
// -
template <>
struct ParamTraits<mozilla::webgl::ActiveInfo> final {
using T = mozilla::webgl::ActiveInfo;
static void Write(Message* const msg, const T& in) {
WriteParam(msg, in.elemType);
WriteParam(msg, in.elemCount);
WriteParam(msg, in.name);
}
static bool Read(const Message* const msg, PickleIterator* const itr,
T* const out) {
return ReadParam(msg, itr, &out->elemType) &&
ReadParam(msg, itr, &out->elemCount) &&
ReadParam(msg, itr, &out->name);
}
};
// -
template <>
struct ParamTraits<mozilla::webgl::ActiveAttribInfo> final {
using T = mozilla::webgl::ActiveAttribInfo;
static void Write(Message* const msg, const T& in) {
WriteParam(msg, static_cast<const mozilla::webgl::ActiveInfo&>(in));
WriteParam(msg, in.location);
WriteParam(msg, in.baseType);
}
static bool Read(const Message* const msg, PickleIterator* const itr,
T* const out) {
return ReadParam(msg, itr, static_cast<mozilla::webgl::ActiveInfo*>(out)) &&
ReadParam(msg, itr, &out->location) &&
ReadParam(msg, itr, &out->baseType);
}
};
// -
template <>
struct ParamTraits<mozilla::webgl::ActiveUniformInfo> final {
using T = mozilla::webgl::ActiveUniformInfo;
static void Write(Message* const msg, const T& in) {
WriteParam(msg, static_cast<const mozilla::webgl::ActiveInfo&>(in));
WriteParam(msg, in.locByIndex);
WriteParam(msg, in.block_index);
WriteParam(msg, in.block_offset);
WriteParam(msg, in.block_arrayStride);
WriteParam(msg, in.block_matrixStride);
WriteParam(msg, in.block_isRowMajor);
}
static bool Read(const Message* const msg, PickleIterator* const itr,
T* const out) {
return ReadParam(msg, itr, static_cast<mozilla::webgl::ActiveInfo*>(out)) &&
ReadParam(msg, itr, &out->locByIndex) &&
ReadParam(msg, itr, &out->block_index) &&
ReadParam(msg, itr, &out->block_offset) &&
ReadParam(msg, itr, &out->block_arrayStride) &&
ReadParam(msg, itr, &out->block_matrixStride) &&
ReadParam(msg, itr, &out->block_isRowMajor);
}
};
// -
template <>
struct ParamTraits<mozilla::webgl::ActiveUniformBlockInfo> final {
using T = mozilla::webgl::ActiveUniformBlockInfo;
static void Write(Message* const msg, const T& in) {
WriteParam(msg, in.name);
WriteParam(msg, in.dataSize);
WriteParam(msg, in.activeUniformIndices);
WriteParam(msg, in.referencedByVertexShader);
WriteParam(msg, in.referencedByFragmentShader);
}
static bool Read(const Message* const msg, PickleIterator* const itr,
T* const out) {
return ReadParam(msg, itr, &out->name) &&
ReadParam(msg, itr, &out->dataSize) &&
ReadParam(msg, itr, &out->activeUniformIndices) &&
ReadParam(msg, itr, &out->referencedByVertexShader) &&
ReadParam(msg, itr, &out->referencedByFragmentShader);
}
};
// -
template <>
struct ParamTraits<mozilla::webgl::ShaderPrecisionFormat> final {
using T = mozilla::webgl::ShaderPrecisionFormat;
static void Write(Message* const msg, const T& in) {
WriteParam(msg, in.rangeMin);
WriteParam(msg, in.rangeMax);
WriteParam(msg, in.precision);
}
static bool Read(const Message* const msg, PickleIterator* const itr,
T* const out) {
return ReadParam(msg, itr, &out->rangeMin) &&
ReadParam(msg, itr, &out->rangeMax) &&
ReadParam(msg, itr, &out->precision);
}
};
// -
template <typename U, size_t N>
struct ParamTraits<U[N]> final {
using T = U[N];
static constexpr size_t kByteSize = sizeof(U) * N;
static_assert(std::is_trivial<U>::value);
static void Write(Message* const msg, const T& in) {
msg->WriteBytes(in, kByteSize);
}
static bool Read(const Message* const msg, PickleIterator* const itr,
T* const out) {
if (!msg->HasBytesAvailable(itr, kByteSize)) {
return false;
}
return msg->ReadBytesInto(itr, *out, kByteSize);
}
};
// -
template <>
struct ParamTraits<mozilla::webgl::GetUniformData> final {
using T = mozilla::webgl::GetUniformData;
static void Write(Message* const msg, const T& in) {
ParamTraits<decltype(in.data)>::Write(msg, in.data);
WriteParam(msg, in.type);
}
static bool Read(const Message* const msg, PickleIterator* const itr,
T* const out) {
return ParamTraits<decltype(out->data)>::Read(msg, itr, &out->data) &&
ReadParam(msg, itr, &out->type);
}
};
// -
template <typename U>
struct ParamTraits<mozilla::avec2<U>> final {
using T = mozilla::avec2<U>;
static void Write(Message* const msg, const T& in) {
WriteParam(msg, in.x);
WriteParam(msg, in.y);
}
static bool Read(const Message* const msg, PickleIterator* const itr,
T* const out) {
return ReadParam(msg, itr, &out->x) && ReadParam(msg, itr, &out->y);
}
};
// -
template <typename U>
struct ParamTraits<mozilla::avec3<U>> final {
using T = mozilla::avec3<U>;
static void Write(Message* const msg, const T& in) {
WriteParam(msg, in.x);
WriteParam(msg, in.y);
WriteParam(msg, in.z);
}
static bool Read(const Message* const msg, PickleIterator* const itr,
T* const out) {
return ReadParam(msg, itr, &out->x) && ReadParam(msg, itr, &out->y) &&
ReadParam(msg, itr, &out->z);
}
};
} // namespace IPC } // namespace IPC
namespace mozilla {
namespace webgl {
using MaybeDouble = Maybe<double>;
using MaybeFrontBufferSnapshotIpc = Maybe<FrontBufferSnapshotIpc>;
using MaybeSurfaceDescriptor = Maybe<layers::SurfaceDescriptor>;
using MaybeReadPixelsResultIpc = Maybe<ReadPixelsResultIpc>;
using MaybeShaderPrecisionFormat = Maybe<ShaderPrecisionFormat>;
using MaybeString = Maybe<std::string>;
} // namespace webgl
} // namespace mozilla
#endif #endif

View File

@@ -19,11 +19,18 @@ template <size_t id = 0>
class WebGLMethodDispatcher class WebGLMethodDispatcher
: public EmptyMethodDispatcher<WebGLMethodDispatcher> {}; : public EmptyMethodDispatcher<WebGLMethodDispatcher> {};
#define DEFINE_METHOD_DISPATCHER(_ID, _METHOD, _SYNC) \ template <typename MethodT, MethodT Method>
template <> \ size_t IdByMethod() = delete;
class WebGLMethodDispatcher<_ID> \
: public MethodDispatcher<WebGLMethodDispatcher, _ID, \ #define DEFINE_METHOD_DISPATCHER(_ID, _METHOD, _SYNC) \
decltype(&_METHOD), &_METHOD, _SYNC> {}; template <> \
class WebGLMethodDispatcher<_ID> \
: public MethodDispatcher<WebGLMethodDispatcher, _ID, \
decltype(&_METHOD), &_METHOD, _SYNC> {}; \
template <> \
inline size_t IdByMethod<decltype(&_METHOD), &_METHOD>() { \
return _ID; \
}
// 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.
@@ -31,12 +38,12 @@ class WebGLMethodDispatcher
DEFINE_METHOD_DISPATCHER(__COUNTER__, _METHOD, _SYNC) DEFINE_METHOD_DISPATCHER(__COUNTER__, _METHOD, _SYNC)
#define DEFINE_ASYNC(_METHOD) \ #define DEFINE_ASYNC(_METHOD) \
DEFINE_METHOD_HELPER(_METHOD, CommandSyncType::ASYNC) DEFINE_METHOD_HELPER(_METHOD, CommandSyncType::ASYNC)
#define DEFINE_SYNC(_METHOD) \ //#define DEFINE_SYNC(_METHOD) \
DEFINE_METHOD_HELPER(_METHOD, CommandSyncType::SYNC) // DEFINE_METHOD_HELPER(_METHOD, CommandSyncType::SYNC)
DEFINE_ASYNC(HostWebGLContext::CreateBuffer) DEFINE_ASYNC(HostWebGLContext::CreateBuffer)
DEFINE_ASYNC(HostWebGLContext::CreateFramebuffer) DEFINE_ASYNC(HostWebGLContext::CreateFramebuffer)
DEFINE_SYNC(HostWebGLContext::CreateOpaqueFramebuffer) // DEFINE_SYNC(HostWebGLContext::CreateOpaqueFramebuffer)
DEFINE_ASYNC(HostWebGLContext::CreateProgram) DEFINE_ASYNC(HostWebGLContext::CreateProgram)
DEFINE_ASYNC(HostWebGLContext::CreateQuery) DEFINE_ASYNC(HostWebGLContext::CreateQuery)
DEFINE_ASYNC(HostWebGLContext::CreateRenderbuffer) DEFINE_ASYNC(HostWebGLContext::CreateRenderbuffer)
@@ -62,26 +69,26 @@ DEFINE_ASYNC(HostWebGLContext::DeleteVertexArray)
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::GetFrontBufferSnapshot) // DEFINE_SYNC(HostWebGLContext::GetFrontBufferSnapshot)
DEFINE_SYNC(HostWebGLContext::GetFragDataLocation) // DEFINE_SYNC(HostWebGLContext::GetFragDataLocation)
DEFINE_SYNC(HostWebGLContext::GetFrontBuffer) // DEFINE_SYNC(HostWebGLContext::GetFrontBuffer)
DEFINE_SYNC(HostWebGLContext::GetLinkResult) // DEFINE_SYNC(HostWebGLContext::GetLinkResult)
DEFINE_SYNC(HostWebGLContext::IsEnabled) // DEFINE_SYNC(HostWebGLContext::IsEnabled)
DEFINE_ASYNC(HostWebGLContext::Resize) DEFINE_ASYNC(HostWebGLContext::Resize)
DEFINE_ASYNC(HostWebGLContext::RequestExtension) DEFINE_ASYNC(HostWebGLContext::RequestExtension)
DEFINE_SYNC(HostWebGLContext::DrawingBufferSize) // DEFINE_SYNC(HostWebGLContext::DrawingBufferSize)
DEFINE_SYNC(HostWebGLContext::OnMemoryPressure) // DEFINE_SYNC(HostWebGLContext::OnMemoryPressure)
DEFINE_ASYNC(HostWebGLContext::DidRefresh) DEFINE_ASYNC(HostWebGLContext::DidRefresh)
DEFINE_SYNC(HostWebGLContext::GetParameter) // DEFINE_SYNC(HostWebGLContext::GetParameter)
DEFINE_SYNC(HostWebGLContext::GetString) // DEFINE_SYNC(HostWebGLContext::GetString)
DEFINE_ASYNC(HostWebGLContext::AttachShader) DEFINE_ASYNC(HostWebGLContext::AttachShader)
DEFINE_ASYNC(HostWebGLContext::BindAttribLocation) DEFINE_ASYNC(HostWebGLContext::BindAttribLocation)
DEFINE_ASYNC(HostWebGLContext::BindFramebuffer) DEFINE_ASYNC(HostWebGLContext::BindFramebuffer)
DEFINE_ASYNC(HostWebGLContext::BlendColor) DEFINE_ASYNC(HostWebGLContext::BlendColor)
DEFINE_ASYNC(HostWebGLContext::BlendEquationSeparate) DEFINE_ASYNC(HostWebGLContext::BlendEquationSeparate)
DEFINE_ASYNC(HostWebGLContext::BlendFuncSeparate) DEFINE_ASYNC(HostWebGLContext::BlendFuncSeparate)
DEFINE_SYNC(HostWebGLContext::CheckFramebufferStatus) // DEFINE_SYNC(HostWebGLContext::CheckFramebufferStatus)
DEFINE_ASYNC(HostWebGLContext::Clear) DEFINE_ASYNC(HostWebGLContext::Clear)
DEFINE_ASYNC(HostWebGLContext::ClearColor) DEFINE_ASYNC(HostWebGLContext::ClearColor)
DEFINE_ASYNC(HostWebGLContext::ClearDepth) DEFINE_ASYNC(HostWebGLContext::ClearDepth)
@@ -94,19 +101,19 @@ DEFINE_ASYNC(HostWebGLContext::DepthMask)
DEFINE_ASYNC(HostWebGLContext::DepthRange) DEFINE_ASYNC(HostWebGLContext::DepthRange)
DEFINE_ASYNC(HostWebGLContext::DetachShader) DEFINE_ASYNC(HostWebGLContext::DetachShader)
DEFINE_ASYNC(HostWebGLContext::Flush) DEFINE_ASYNC(HostWebGLContext::Flush)
DEFINE_SYNC(HostWebGLContext::Finish) // DEFINE_SYNC(HostWebGLContext::Finish)
DEFINE_ASYNC(HostWebGLContext::FramebufferAttach) DEFINE_ASYNC(HostWebGLContext::FramebufferAttach)
DEFINE_ASYNC(HostWebGLContext::FrontFace) DEFINE_ASYNC(HostWebGLContext::FrontFace)
DEFINE_SYNC(HostWebGLContext::GetBufferParameter) // DEFINE_SYNC(HostWebGLContext::GetBufferParameter)
DEFINE_SYNC(HostWebGLContext::GetError) // DEFINE_SYNC(HostWebGLContext::GetError)
DEFINE_SYNC(HostWebGLContext::GetFramebufferAttachmentParameter) // DEFINE_SYNC(HostWebGLContext::GetFramebufferAttachmentParameter)
DEFINE_SYNC(HostWebGLContext::GetRenderbufferParameter) // DEFINE_SYNC(HostWebGLContext::GetRenderbufferParameter)
DEFINE_SYNC(HostWebGLContext::GetShaderPrecisionFormat) // DEFINE_SYNC(HostWebGLContext::GetShaderPrecisionFormat)
DEFINE_SYNC(HostWebGLContext::GetUniform) // DEFINE_SYNC(HostWebGLContext::GetUniform)
DEFINE_ASYNC(HostWebGLContext::Hint) DEFINE_ASYNC(HostWebGLContext::Hint)
DEFINE_ASYNC(HostWebGLContext::LineWidth) DEFINE_ASYNC(HostWebGLContext::LineWidth)
DEFINE_ASYNC(HostWebGLContext::LinkProgram) DEFINE_ASYNC(HostWebGLContext::LinkProgram)
DEFINE_SYNC(HostWebGLContext::PixelStorei) DEFINE_ASYNC(HostWebGLContext::PixelStorei)
DEFINE_ASYNC(HostWebGLContext::PolygonOffset) DEFINE_ASYNC(HostWebGLContext::PolygonOffset)
DEFINE_ASYNC(HostWebGLContext::Present) DEFINE_ASYNC(HostWebGLContext::Present)
DEFINE_ASYNC(HostWebGLContext::SampleCoverage) DEFINE_ASYNC(HostWebGLContext::SampleCoverage)
@@ -135,18 +142,18 @@ 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)
DEFINE_ASYNC(HostWebGLContext::UseProgram) DEFINE_ASYNC(HostWebGLContext::UseProgram)
DEFINE_SYNC(HostWebGLContext::ValidateProgram) // DEFINE_SYNC(HostWebGLContext::ValidateProgram)
DEFINE_ASYNC(HostWebGLContext::UniformData) DEFINE_ASYNC(HostWebGLContext::UniformData)
DEFINE_ASYNC(HostWebGLContext::VertexAttrib4T) DEFINE_ASYNC(HostWebGLContext::VertexAttrib4T)
DEFINE_ASYNC(HostWebGLContext::VertexAttribDivisor) DEFINE_ASYNC(HostWebGLContext::VertexAttribDivisor)
DEFINE_SYNC(HostWebGLContext::GetIndexedParameter) // DEFINE_SYNC(HostWebGLContext::GetIndexedParameter)
DEFINE_ASYNC(HostWebGLContext::UniformBlockBinding) DEFINE_ASYNC(HostWebGLContext::UniformBlockBinding)
DEFINE_ASYNC(HostWebGLContext::EnableVertexAttribArray) DEFINE_ASYNC(HostWebGLContext::EnableVertexAttribArray)
DEFINE_ASYNC(HostWebGLContext::DisableVertexAttribArray) DEFINE_ASYNC(HostWebGLContext::DisableVertexAttribArray)
DEFINE_SYNC(HostWebGLContext::GetVertexAttrib) // 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)
@@ -155,8 +162,8 @@ DEFINE_ASYNC(HostWebGLContext::ReadPixelsPbo)
DEFINE_ASYNC(HostWebGLContext::BindSampler) DEFINE_ASYNC(HostWebGLContext::BindSampler)
DEFINE_ASYNC(HostWebGLContext::SamplerParameteri) DEFINE_ASYNC(HostWebGLContext::SamplerParameteri)
DEFINE_ASYNC(HostWebGLContext::SamplerParameterf) DEFINE_ASYNC(HostWebGLContext::SamplerParameterf)
DEFINE_SYNC(HostWebGLContext::GetSamplerParameter) // DEFINE_SYNC(HostWebGLContext::GetSamplerParameter)
DEFINE_SYNC(HostWebGLContext::ClientWaitSync) // DEFINE_SYNC(HostWebGLContext::ClientWaitSync)
DEFINE_ASYNC(HostWebGLContext::BindTransformFeedback) DEFINE_ASYNC(HostWebGLContext::BindTransformFeedback)
DEFINE_ASYNC(HostWebGLContext::BeginTransformFeedback) DEFINE_ASYNC(HostWebGLContext::BeginTransformFeedback)
DEFINE_ASYNC(HostWebGLContext::EndTransformFeedback) DEFINE_ASYNC(HostWebGLContext::EndTransformFeedback)
@@ -170,13 +177,13 @@ DEFINE_ASYNC(HostWebGLContext::DrawElementsInstanced)
DEFINE_ASYNC(HostWebGLContext::BeginQuery) DEFINE_ASYNC(HostWebGLContext::BeginQuery)
DEFINE_ASYNC(HostWebGLContext::EndQuery) DEFINE_ASYNC(HostWebGLContext::EndQuery)
DEFINE_ASYNC(HostWebGLContext::QueryCounter) DEFINE_ASYNC(HostWebGLContext::QueryCounter)
DEFINE_SYNC(HostWebGLContext::GetQueryParameter) // DEFINE_SYNC(HostWebGLContext::GetQueryParameter)
DEFINE_ASYNC(HostWebGLContext::SetFramebufferIsInOpaqueRAF) DEFINE_ASYNC(HostWebGLContext::SetFramebufferIsInOpaqueRAF)
DEFINE_ASYNC(HostWebGLContext::ClearVRSwapChain) DEFINE_ASYNC(HostWebGLContext::ClearVRSwapChain)
#undef DEFINE_METHOD_HELPER #undef DEFINE_METHOD_HELPER
#undef DEFINE_ASYNC #undef DEFINE_ASYNC
#undef DEFINE_SYNC //#undef DEFINE_SYNC
#undef DEFINE_METHOD_DISPATCHER #undef DEFINE_METHOD_DISPATCHER
} // namespace mozilla } // namespace mozilla

View File

@@ -10,6 +10,7 @@
#include "mozilla/layers/LayerTransactionParent.h" #include "mozilla/layers/LayerTransactionParent.h"
#include "mozilla/layers/TextureClientSharedSurface.h" #include "mozilla/layers/TextureClientSharedSurface.h"
#include "HostWebGLContext.h" #include "HostWebGLContext.h"
#include "WebGLMethodDispatcher.h"
namespace mozilla { namespace mozilla {
@@ -35,84 +36,37 @@ mozilla::ipc::IPCResult WebGLParent::RecvInitialize(
return IPC_FAIL(this, "Failed to create HostWebGLContext"); return IPC_FAIL(this, "Failed to create HostWebGLContext");
} }
if (!BeginCommandQueueDrain()) {
return IPC_FAIL(this, "Failed to start WebGL command queue drain");
}
return IPC_OK(); return IPC_OK();
} }
WebGLParent::WebGLParent() : PcqActor(this) {} WebGLParent::WebGLParent() : PcqActor(this) {}
WebGLParent::~WebGLParent() = default; WebGLParent::~WebGLParent() = default;
bool WebGLParent::BeginCommandQueueDrain() { // -
if (mRunCommandsRunnable) {
// already running using IPCResult = mozilla::ipc::IPCResult;
return true;
IPCResult WebGLParent::RecvDispatchCommands(Shmem&& shmem,
const uint64_t cmdsByteSize) {
MOZ_ASSERT(cmdsByteSize);
const auto shmemBytes = ByteRange(shmem);
const auto byteSize = std::min<uint64_t>(shmemBytes.length(), cmdsByteSize);
const auto cmdsBytes =
Range<const uint8_t>{shmemBytes.begin(), shmemBytes.begin() + byteSize};
auto view = webgl::RangeConsumerView{cmdsBytes};
while (true) {
size_t id = 0;
const auto status = view.ReadParam(&id);
if (status != QueueStatus::kSuccess) break;
WebGLMethodDispatcher<0>::DispatchCommand(*mHost, id, view);
} }
WeakPtr<WebGLParent> weakThis = this; return IPC_OK();
mRunCommandsRunnable = NS_NewRunnableFunction(
"RunWebGLCommands", [weakThis]() { MaybeRunCommandQueue(weakThis); });
if (!mRunCommandsRunnable) {
MOZ_ASSERT_UNREACHABLE("Failed to create RunWebGLCommands Runnable");
return false;
}
// Start the recurring runnable.
return RunCommandQueue();
} }
/* static */ bool WebGLParent::MaybeRunCommandQueue( // -
const WeakPtr<WebGLParent>& weakWebGLParent) {
// We don't have to worry about WebGLParent being deleted from under us
// as its not thread-safe so we must be the only thread using it. In fact,
// WeakRef cannot atomically promote to a RefPtr so it is not thread safe
// either.
if (weakWebGLParent) {
// This will re-issue the task if the queue is still running.
return weakWebGLParent->RunCommandQueue();
}
// Context was deleted. Do not re-issue the task.
return true;
}
bool WebGLParent::RunCommandQueue() {
if (!mRunCommandsRunnable) {
// The actor finished. Do not re-issue the task.
return true;
}
MOZ_CRASH("todo");
/*
// Drain the queue for up to kMaxWebGLCommandTimeSliceMs, then
// repeat no sooner than kDrainDelayMs later.
// TODO: Tune these.
static const uint32_t kMaxWebGLCommandTimeSliceMs = 1;
static const uint32_t kDrainDelayMs = 0;
TimeDuration timeSlice =
TimeDuration::FromMilliseconds(kMaxWebGLCommandTimeSliceMs);
CommandResult result = mHost->RunCommandsForDuration(timeSlice);
bool success = (result == CommandResult::Success) ||
(result == CommandResult::QueueEmpty);
if (!success) {
// Tell client that this WebGLParent needs to be shut down
WEBGL_BRIDGE_LOGE("WebGLParent failed while running commands");
(void)SendOnContextLoss(webgl::ContextLossReason::None);
mRunCommandsRunnable = nullptr;
return false;
}
// Re-issue the task
MOZ_ASSERT(mRunCommandsRunnable);
MOZ_ASSERT(GetCurrentSerialEventTarget());
GetCurrentSerialEventTarget()->DelayedDispatch(do_AddRef(mRunCommandsRunnable),
kDrainDelayMs);
*/
return true;
}
mozilla::ipc::IPCResult WebGLParent::Recv__delete__() { mozilla::ipc::IPCResult WebGLParent::Recv__delete__() {
mHost = nullptr; mHost = nullptr;
@@ -121,18 +75,224 @@ mozilla::ipc::IPCResult WebGLParent::Recv__delete__() {
void WebGLParent::ActorDestroy(ActorDestroyReason aWhy) { mHost = nullptr; } void WebGLParent::ActorDestroy(ActorDestroyReason aWhy) { mHost = nullptr; }
mozilla::ipc::IPCResult WebGLParent::RecvUpdateCompositableHandle( // -
layers::PLayerTransactionParent* aLayerTransaction,
const CompositableHandle& aHandle) { IPCResult WebGLParent::RecvGetFrontBufferSnapshot(
auto layerTrans = webgl::FrontBufferSnapshotIpc* const ret) {
static_cast<layers::LayerTransactionParent*>(aLayerTransaction); *ret = {};
RefPtr<layers::CompositableHost> compositableHost(
layerTrans->FindCompositable(aHandle)); const auto surfSize = mHost->GetFrontBufferSize();
if (!compositableHost) { const auto byteSize = 4 * surfSize.x * surfSize.y;
return IPC_FAIL(this, "Failed to find CompositableHost for WebGL instance");
Shmem shmem;
if (!PWebGLParent::AllocShmem(
byteSize, mozilla::ipc::SharedMemory::SharedMemoryType::TYPE_BASIC,
&shmem)) {
return IPC_FAIL(this, "Failed to allocate shmem for result");
} }
mHost->SetCompositableHost(compositableHost); auto shmemBytes = ByteRange(shmem);
if (!mHost->FrontBufferSnapshotInto(shmemBytes)) return IPC_OK();
*ret = {surfSize, Some(std::move(shmem))};
return IPC_OK();
}
IPCResult WebGLParent::RecvGetBufferSubData(const GLenum target,
const uint64_t srcByteOffset,
const uint64_t byteSize,
Shmem* const ret) {
Shmem shmem;
if (!PWebGLParent::AllocShmem(
byteSize, mozilla::ipc::SharedMemory::SharedMemoryType::TYPE_BASIC,
&shmem)) {
MOZ_ASSERT(false);
return IPC_FAIL(this, "Failed to allocate shmem for result");
}
const auto range = ByteRange(shmem);
memset(range.begin().get(), 0,
range.length()); // TODO: This is usually overkill.
if (mHost->GetBufferSubData(target, srcByteOffset, range)) {
*ret = std::move(shmem);
}
return IPC_OK();
}
IPCResult WebGLParent::RecvReadPixels(const webgl::ReadPixelsDesc& desc,
const uint64_t byteCount,
webgl::ReadPixelsResultIpc* const ret) {
*ret = {};
Shmem shmem;
if (!PWebGLParent::AllocShmem(
byteCount, mozilla::ipc::SharedMemory::SharedMemoryType::TYPE_BASIC,
&shmem)) {
MOZ_ASSERT(false);
return IPC_FAIL(this, "Failed to allocate shmem for result");
}
auto range = ByteRange(shmem);
memset(range.begin().get(), 0,
range.length()); // TODO: This is usually overkill.
const auto res = mHost->ReadPixelsInto(desc, range);
*ret = {res, std::move(shmem)};
return IPC_OK();
}
// -
IPCResult WebGLParent::RecvCheckFramebufferStatus(GLenum target,
GLenum* const ret) {
*ret = mHost->CheckFramebufferStatus(target);
return IPC_OK();
}
IPCResult WebGLParent::RecvClientWaitSync(ObjectId id, GLbitfield flags,
GLuint64 timeout, GLenum* const ret) {
*ret = mHost->ClientWaitSync(id, flags, timeout);
return IPC_OK();
}
IPCResult WebGLParent::RecvCreateOpaqueFramebuffer(
const ObjectId id, const OpaqueFramebufferOptions& options,
bool* const ret) {
*ret = mHost->CreateOpaqueFramebuffer(id, options);
return IPC_OK();
}
IPCResult WebGLParent::RecvDrawingBufferSize(uvec2* const ret) {
*ret = mHost->DrawingBufferSize();
return IPC_OK();
}
IPCResult WebGLParent::RecvFinish() {
mHost->Finish();
return IPC_OK();
}
IPCResult WebGLParent::RecvGetBufferParameter(GLenum target, GLenum pname,
Maybe<double>* const ret) {
*ret = mHost->GetBufferParameter(target, pname);
return IPC_OK();
}
IPCResult WebGLParent::RecvGetCompileResult(ObjectId id,
webgl::CompileResult* const ret) {
*ret = mHost->GetCompileResult(id);
return IPC_OK();
}
IPCResult WebGLParent::RecvGetError(GLenum* const ret) {
*ret = mHost->GetError();
return IPC_OK();
}
IPCResult WebGLParent::RecvGetFragDataLocation(ObjectId id,
const std::string& name,
GLint* const ret) {
*ret = mHost->GetFragDataLocation(id, name);
return IPC_OK();
}
IPCResult WebGLParent::RecvGetFramebufferAttachmentParameter(
ObjectId id, GLenum attachment, GLenum pname, Maybe<double>* const ret) {
*ret = mHost->GetFramebufferAttachmentParameter(id, attachment, pname);
return IPC_OK();
}
IPCResult WebGLParent::RecvGetFrontBuffer(
ObjectId fb, const bool vr, Maybe<layers::SurfaceDescriptor>* const ret) {
*ret = mHost->GetFrontBuffer(fb, vr);
return IPC_OK();
}
IPCResult WebGLParent::RecvGetIndexedParameter(GLenum target, GLuint index,
Maybe<double>* const ret) {
*ret = mHost->GetIndexedParameter(target, index);
return IPC_OK();
}
IPCResult WebGLParent::RecvGetInternalformatParameter(
const GLenum target, const GLuint format, const GLuint pname,
Maybe<std::vector<int32_t>>* const ret) {
*ret = mHost->GetInternalformatParameter(target, format, pname);
return IPC_OK();
}
IPCResult WebGLParent::RecvGetLinkResult(ObjectId id,
webgl::LinkResult* const ret) {
*ret = mHost->GetLinkResult(id);
return IPC_OK();
}
IPCResult WebGLParent::RecvGetNumber(GLenum pname, Maybe<double>* const ret) {
*ret = mHost->GetNumber(pname);
return IPC_OK();
}
IPCResult WebGLParent::RecvGetQueryParameter(ObjectId id, GLenum pname,
Maybe<double>* const ret) {
*ret = mHost->GetQueryParameter(id, pname);
return IPC_OK();
}
IPCResult WebGLParent::RecvGetRenderbufferParameter(ObjectId id, GLenum pname,
Maybe<double>* const ret) {
*ret = mHost->GetRenderbufferParameter(id, pname);
return IPC_OK();
}
IPCResult WebGLParent::RecvGetSamplerParameter(ObjectId id, GLenum pname,
Maybe<double>* const ret) {
*ret = mHost->GetSamplerParameter(id, pname);
return IPC_OK();
}
IPCResult WebGLParent::RecvGetShaderPrecisionFormat(
GLenum shaderType, GLenum precisionType,
Maybe<webgl::ShaderPrecisionFormat>* const ret) {
*ret = mHost->GetShaderPrecisionFormat(shaderType, precisionType);
return IPC_OK();
}
IPCResult WebGLParent::RecvGetString(GLenum pname,
Maybe<std::string>* const ret) {
*ret = mHost->GetString(pname);
return IPC_OK();
}
IPCResult WebGLParent::RecvGetTexParameter(ObjectId id, GLenum pname,
Maybe<double>* const ret) {
*ret = mHost->GetTexParameter(id, pname);
return IPC_OK();
}
IPCResult WebGLParent::RecvGetUniform(ObjectId id, uint32_t loc,
webgl::GetUniformData* const ret) {
*ret = mHost->GetUniform(id, loc);
return IPC_OK();
}
IPCResult WebGLParent::RecvGetVertexAttrib(GLuint index, GLenum pname,
Maybe<double>* const ret) {
*ret = mHost->GetVertexAttrib(index, pname);
return IPC_OK();
}
IPCResult WebGLParent::RecvIsEnabled(GLenum cap, bool* const ret) {
*ret = mHost->IsEnabled(cap);
return IPC_OK();
}
IPCResult WebGLParent::RecvOnMemoryPressure() {
mHost->OnMemoryPressure();
return IPC_OK();
}
IPCResult WebGLParent::RecvValidateProgram(ObjectId id, bool* const ret) {
*ret = mHost->ValidateProgram(id);
return IPC_OK(); return IPC_OK();
} }

View File

@@ -17,13 +17,12 @@ class HostWebGLContext;
namespace layers { namespace layers {
class SharedSurfaceTextureClient; class SharedSurfaceTextureClient;
class SurfaceDescriptor;
} }
namespace dom { namespace dom {
class WebGLParent : public PWebGLParent, class WebGLParent : public PWebGLParent,
public AsyncProducerActor<WebGLParent>,
public SyncConsumerActor<WebGLParent>,
public SupportsWeakPtr<WebGLParent>, public SupportsWeakPtr<WebGLParent>,
public mozilla::webgl::PcqActor { public mozilla::webgl::PcqActor {
friend PWebGLParent; friend PWebGLParent;
@@ -37,22 +36,72 @@ class WebGLParent : public PWebGLParent,
const webgl::InitContextDesc&, UniquePtr<HostWebGLCommandSinkP>&& aSinkP, const webgl::InitContextDesc&, UniquePtr<HostWebGLCommandSinkP>&& aSinkP,
UniquePtr<HostWebGLCommandSinkI>&& aSinkI, webgl::InitContextResult* out); UniquePtr<HostWebGLCommandSinkI>&& aSinkI, webgl::InitContextResult* out);
// Drain the command queue now. Used by synchronous IpdlQueue consumers.
bool RunQueue(uint64_t) { return RunCommandQueue(); }
WebGLParent(); // For IPDL WebGLParent(); // For IPDL
using IPCResult = mozilla::ipc::IPCResult;
IPCResult RecvDispatchCommands(mozilla::ipc::Shmem&&, uint64_t);
IPCResult RecvGetFrontBufferSnapshot(webgl::FrontBufferSnapshotIpc* ret);
IPCResult RecvReadPixels(const webgl::ReadPixelsDesc&, uint64_t byteSize,
webgl::ReadPixelsResultIpc* ret);
// -
using ObjectId = webgl::ObjectId;
IPCResult RecvCheckFramebufferStatus(GLenum target, GLenum* ret);
IPCResult RecvClientWaitSync(ObjectId id, GLbitfield flags, GLuint64 timeout,
GLenum* ret);
IPCResult RecvCreateOpaqueFramebuffer(ObjectId id,
const OpaqueFramebufferOptions&,
bool* ret);
IPCResult RecvDrawingBufferSize(uvec2* ret);
IPCResult RecvFinish();
IPCResult RecvGetBufferParameter(GLenum target, GLenum pname,
Maybe<double>* ret);
IPCResult RecvGetBufferSubData(GLenum target, uint64_t srcByteOffset,
uint64_t byteSize, mozilla::ipc::Shmem* ret);
IPCResult RecvGetCompileResult(ObjectId id, webgl::CompileResult* ret);
IPCResult RecvGetError(GLenum* ret);
IPCResult RecvGetFragDataLocation(ObjectId id, const std::string& name,
GLint* ret);
IPCResult RecvGetFramebufferAttachmentParameter(ObjectId id,
GLenum attachment,
GLenum pname,
Maybe<double>* ret);
IPCResult RecvGetFrontBuffer(ObjectId fb, bool vr,
Maybe<layers::SurfaceDescriptor>* ret);
IPCResult RecvGetIndexedParameter(GLenum target, GLuint index,
Maybe<double>* ret);
IPCResult RecvGetInternalformatParameter(GLenum target, GLuint format,
GLuint pname,
Maybe<std::vector<int32_t>>* ret);
IPCResult RecvGetLinkResult(ObjectId id, webgl::LinkResult* ret);
IPCResult RecvGetNumber(GLenum pname, Maybe<double>* ret);
IPCResult RecvGetQueryParameter(ObjectId id, GLenum pname,
Maybe<double>* ret);
IPCResult RecvGetRenderbufferParameter(ObjectId id, GLenum pname,
Maybe<double>* ret);
IPCResult RecvGetSamplerParameter(ObjectId id, GLenum pname,
Maybe<double>* ret);
IPCResult RecvGetShaderPrecisionFormat(
GLenum shaderType, GLenum precisionType,
Maybe<webgl::ShaderPrecisionFormat>* ret);
IPCResult RecvGetString(GLenum pname, Maybe<std::string>* ret);
IPCResult RecvGetTexParameter(ObjectId id, GLenum pname, Maybe<double>* ret);
IPCResult RecvGetUniform(ObjectId id, uint32_t loc,
webgl::GetUniformData* ret);
IPCResult RecvGetVertexAttrib(GLuint index, GLenum pname, Maybe<double>* ret);
IPCResult RecvIsEnabled(GLenum cap, bool* ret);
IPCResult RecvOnMemoryPressure();
IPCResult RecvValidateProgram(ObjectId id, bool* ret);
// -
private: private:
~WebGLParent(); ~WebGLParent();
bool BeginCommandQueueDrain();
static bool MaybeRunCommandQueue(const WeakPtr<WebGLParent>& weakWebGLParent);
bool RunCommandQueue();
mozilla::ipc::IPCResult RecvUpdateCompositableHandle(
layers::PLayerTransactionParent* aLayerTransaction,
const CompositableHandle& aHandle);
mozilla::ipc::IPCResult Recv__delete__() override; mozilla::ipc::IPCResult Recv__delete__() override;
void ActorDestroy(ActorDestroyReason aWhy) override; void ActorDestroy(ActorDestroyReason aWhy) override;

View File

@@ -70,62 +70,52 @@ struct QueueParamTraits<RawBuffer<T>> {
using ParamType = RawBuffer<T>; using ParamType = RawBuffer<T>;
template <typename U> template <typename U>
static QueueStatus Write(ProducerView<U>& aProducerView, static QueueStatus Write(ProducerView<U>& view, const ParamType& in) {
const ParamType& aArg) { const auto range = in.Data();
aProducerView.WriteParam(aArg.mLength);
return (aArg.mLength > 0) const auto elemCount = range.length();
? aProducerView.Write(aArg.mData, aArg.mLength * sizeof(T)) auto status = view.WriteParam(elemCount);
: aProducerView.GetStatus(); if (!status) return status;
if (!elemCount) return status;
const bool hasData = bool(range.begin().get());
status = view.WriteParam(hasData);
if (!status) return status;
if (!hasData) return status;
status = view.Write(range.begin().get(), range.end().get());
return status;
} }
template <typename U, typename ElementType = typename std::remove_cv_t< template <typename U>
typename ParamType::ElementType>> static QueueStatus Read(ConsumerView<U>& view, ParamType* const out) {
static QueueStatus Read(ConsumerView<U>& aConsumerView, ParamType* aArg) { size_t elemCount = 0;
size_t len; auto status = view.ReadParam(&elemCount);
QueueStatus status = aConsumerView.ReadParam(&len); if (!status) return status;
if (!status) { if (!elemCount) {
return status; *out = {};
}
if (len == 0) {
aArg->mLength = 0;
aArg->mData = nullptr;
return QueueStatus::kSuccess; return QueueStatus::kSuccess;
} }
struct RawBufferReadMatcher { bool hasData = false;
QueueStatus operator()(RefPtr<mozilla::ipc::SharedMemoryBasic>& smem) { status = view.ReadParam(&hasData);
if (!smem) { if (!status) return status;
return QueueStatus::kFatalError; if (!hasData) {
} auto temp = RawBuffer<T>{Range<T>{nullptr, elemCount}};
mArg->mSmem = smem; *out = std::move(temp);
mArg->mData = static_cast<ElementType*>(smem->memory()); return QueueStatus::kSuccess;
mArg->mLength = mLength; }
mArg->mOwnsData = false;
return QueueStatus::kSuccess;
}
QueueStatus operator()() {
mArg->mSmem = nullptr;
ElementType* buf = new ElementType[mLength];
mArg->mData = buf;
mArg->mLength = mLength;
mArg->mOwnsData = true;
return mConsumerView.Read(buf, mLength * sizeof(T));
}
ConsumerView<U>& mConsumerView; auto buffer = UniqueBuffer::Alloc(elemCount * sizeof(T));
ParamType* mArg; if (!buffer) return QueueStatus::kOOMError;
size_t mLength;
};
return aConsumerView.ReadVariant( using MutT = std::remove_cv_t<T>;
len * sizeof(T), RawBufferReadMatcher{aConsumerView, aArg, len}); const auto begin = reinterpret_cast<MutT*>(buffer.get());
} const auto range = Range<MutT>{begin, elemCount};
template <typename View> auto temp = RawBuffer<T>{range, std::move(buffer)};
static size_t MinSize(View& aView, const ParamType& aArg) { *out = std::move(temp);
return aView.MinSizeParam(aArg.mLength) + return view.Read(range.begin().get(), range.end().get());
aView.MinSizeBytes(aArg.mLength * sizeof(T));
} }
}; };
@@ -168,19 +158,6 @@ struct QueueParamTraits<Result<V, E>> {
} }
return status; return status;
} }
template <typename View>
static size_t MinSize(View& aView, const T& aArg) {
auto size = aView.template MinSizeParam<bool>();
if (aArg.isOk()) {
const auto& val = aArg.unwrap();
size += aView.MinSizeParam(val);
} else {
const auto& val = aArg.unwrapErr();
size += aView.MinSizeParam(val);
}
return size;
}
}; };
template <> template <>
@@ -191,7 +168,7 @@ struct QueueParamTraits<std::string> {
static QueueStatus Write(ProducerView<U>& 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.data() + aArg.size());
return status; return status;
} }
@@ -205,17 +182,10 @@ struct QueueParamTraits<std::string> {
const auto dest = static_cast<char*>(temp.get()); const auto dest = static_cast<char*>(temp.get());
if (!dest) return QueueStatus::kFatalError; if (!dest) return QueueStatus::kFatalError;
status = aConsumerView.Read(dest, size); status = aConsumerView.Read(dest, dest + size);
aArg->assign(dest, size); aArg->assign(dest, size);
return status; return status;
} }
template <typename View>
static size_t MinSize(View& aView, const T& aArg) {
auto size = aView.MinSizeParam(aArg.size());
size += aView.MinSizeBytes(aArg.size());
return size;
}
}; };
template <typename U> template <typename U>
@@ -226,7 +196,7 @@ struct QueueParamTraits<std::vector<U>> {
static QueueStatus Write(ProducerView<V>& 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.data() + aArg.size());
return status; return status;
} }
@@ -238,16 +208,9 @@ struct QueueParamTraits<std::vector<U>> {
if (!status) return status; if (!status) return status;
aArg->resize(size); aArg->resize(size);
status = aConsumerView.Read(aArg->data(), size); status = aConsumerView.Read(aArg->data(), aArg->data() + size);
return status; return status;
} }
template <typename View>
static size_t MinSize(View& aView, const T& aArg) {
auto size = aView.MinSizeParam(aArg.size());
size += aView.MinSizeBytes(aArg.size() * sizeof(U));
return size;
}
}; };
template <> template <>
@@ -275,13 +238,6 @@ struct QueueParamTraits<CompileResult> {
aConsumerView.ReadParam(&aArg->translatedSource); aConsumerView.ReadParam(&aArg->translatedSource);
return aConsumerView.ReadParam(&aArg->success); return aConsumerView.ReadParam(&aArg->success);
} }
template <typename View>
static size_t MinSize(View& aView, const T& aArg) {
return aView.MinSizeParam(aArg.pending) + aView.MinSizeParam(aArg.log) +
aView.MinSizeParam(aArg.translatedSource) +
aView.MinSizeParam(aArg.success);
}
}; };
} // namespace webgl } // namespace webgl

View File

@@ -18,6 +18,7 @@
#include "mozilla/Range.h" #include "mozilla/Range.h"
#include "mozilla/RefCounted.h" #include "mozilla/RefCounted.h"
#include "mozilla/gfx/Point.h" #include "mozilla/gfx/Point.h"
#include "mozilla/ipc/Shmem.h"
#include "gfxTypes.h" #include "gfxTypes.h"
#include "nsTArray.h" #include "nsTArray.h"
@@ -256,6 +257,10 @@ class UniqueBuffer {
void* mBuffer; void* mBuffer;
public: public:
static inline UniqueBuffer Alloc(const size_t byteSize) {
return {malloc(byteSize)};
}
UniqueBuffer() : mBuffer(nullptr) {} UniqueBuffer() : mBuffer(nullptr) {}
MOZ_IMPLICIT UniqueBuffer(void* buffer) : mBuffer(buffer) {} MOZ_IMPLICIT UniqueBuffer(void* buffer) : mBuffer(buffer) {}
@@ -610,21 +615,18 @@ enum class LossStatus {
struct CompileResult final { struct CompileResult final {
bool pending = true; bool pending = true;
std::string log; nsCString log;
std::string translatedSource; nsCString translatedSource;
bool success = false; bool success = false;
}; };
// - // -
struct OpaqueFramebufferOptions { struct OpaqueFramebufferOptions final {
bool depthStencil = true; bool depthStencil = true;
bool antialias = true; bool antialias = true;
uint32_t width = 0; uint32_t width = 0;
uint32_t height = 0; uint32_t height = 0;
OpaqueFramebufferOptions() = default;
OpaqueFramebufferOptions(const OpaqueFramebufferOptions&) = default;
}; };
// - // -
@@ -668,7 +670,7 @@ struct LinkActiveInfo final {
struct LinkResult final { struct LinkResult final {
bool pending = true; bool pending = true;
std::string log; nsCString log;
bool success = false; bool success = false;
LinkActiveInfo active; LinkActiveInfo active;
GLenum tfBufferMode = 0; GLenum tfBufferMode = 0;
@@ -688,6 +690,20 @@ struct GetUniformData final {
GLenum type = 0; GLenum type = 0;
}; };
struct FrontBufferSnapshotIpc final {
uvec2 surfSize = {};
Maybe<mozilla::ipc::Shmem> shmem;
};
struct ReadPixelsResult {
gfx::IntRect subrect = {};
size_t byteStride = 0;
};
struct ReadPixelsResultIpc final : public ReadPixelsResult {
mozilla::ipc::Shmem shmem = {};
};
struct VertAttribPointerDesc final { struct VertAttribPointerDesc final {
bool intFunc = false; bool intFunc = false;
uint8_t channels = 4; uint8_t channels = 4;
@@ -714,23 +730,13 @@ struct ICRData {
/** /**
* Represents a block of memory that it may or may not own. The * Represents a block of memory that it may or may not own. The
* inner data type must be trivially copyable by memcpy. A RawBuffer * inner data type must be trivially copyable by memcpy.
* may be backed by local memory or shared memory.
*/ */
template <typename T = uint8_t, typename nonCV = std::remove_cv_t<T>, template <typename T = uint8_t>
std::enable_if_t<std::is_trivially_assignable<nonCV&, nonCV>::value,
int> = 0>
class RawBuffer { class RawBuffer {
// The SharedMemoryBasic that owns mData, if any. const T* mBegin = nullptr;
RefPtr<mozilla::ipc::SharedMemoryBasic> mSmem; size_t mLen = 0;
// Pointer to the raw memory block UniqueBuffer mOwned;
T* mData = nullptr;
// Length is the number of elements of size T in the array
size_t mLength = 0;
// true if we should delete[] the mData on destruction
bool mOwnsData = false;
friend struct mozilla::webgl::QueueParamTraits<RawBuffer<T>>;
public: public:
using ElementType = T; using ElementType = T;
@@ -738,69 +744,30 @@ class RawBuffer {
/** /**
* If aTakeData is true, RawBuffer will delete[] the memory when destroyed. * If aTakeData is true, RawBuffer will delete[] the memory when destroyed.
*/ */
RawBuffer(size_t len, T* data, bool aTakeData = false) explicit RawBuffer(const Range<const T>& data, UniqueBuffer&& owned = {})
: mData(data), mLength(len), mOwnsData(aTakeData) {} : mBegin(data.begin().get()),
mLen(data.length()),
mOwned(std::move(owned)) {}
RawBuffer(size_t len, RefPtr<mozilla::ipc::SharedMemoryBasic>& aSmem) ~RawBuffer() = default;
: mSmem(aSmem), mData(aSmem->memory()), mLength(len), mOwnsData(false) {
MOZ_ASSERT(mData && mLength);
}
~RawBuffer() { Range<const T> Data() const { return {mBegin, mLen}; }
// If we have a SharedMemoryBasic then it must own mData.
MOZ_ASSERT((!mSmem) || (!mOwnsData));
if (mOwnsData) {
delete[] mData;
}
if (mSmem) {
mSmem->CloseHandle();
}
}
auto Length() const { return mLength; }
T* Data() { return mData; }
const T* Data() const { return mData; }
T& operator[](size_t idx) {
MOZ_ASSERT(mData && (idx < mLength));
return mData[idx];
}
const T& operator[](size_t idx) const {
MOZ_ASSERT(mData && (idx < mLength));
return mData[idx];
}
RawBuffer() = default; RawBuffer() = default;
RawBuffer(const RawBuffer&) = delete; RawBuffer(const RawBuffer&) = delete;
RawBuffer& operator=(const RawBuffer&) = delete; RawBuffer& operator=(const RawBuffer&) = delete;
RawBuffer(RawBuffer&& o) RawBuffer(RawBuffer&&) = default;
: mSmem(o.mSmem), RawBuffer& operator=(RawBuffer&&) = default;
mData(o.mData),
mLength(o.mLength),
mOwnsData(o.mOwnsData) {
o.mSmem = nullptr;
o.mData = nullptr;
o.mLength = 0;
o.mOwnsData = false;
}
RawBuffer& operator=(RawBuffer&& o) {
mSmem = o.mSmem;
mData = o.mData;
mLength = o.mLength;
mOwnsData = o.mOwnsData;
o.mSmem = nullptr;
o.mData = nullptr;
o.mLength = 0;
o.mOwnsData = false;
return *this;
}
}; };
// - // -
struct CopyableRange final : public Range<const uint8_t> {};
// -
// clang-format off // clang-format off
#define FOREACH_ID(X) \ #define FOREACH_ID(X) \
@@ -928,6 +895,12 @@ struct TexImageSource {
// --------------------------------------- // ---------------------------------------
// MakeRange // MakeRange
inline Range<uint8_t> ByteRange(const mozilla::ipc::Shmem& shmem) {
return {shmem.get<uint8_t>(), shmem.Size<uint8_t>()};
}
// -
template <typename T, size_t N> template <typename T, size_t N>
inline Range<const T> MakeRange(T (&arr)[N]) { inline Range<const T> MakeRange(T (&arr)[N]) {
return {arr, N}; return {arr, N};
@@ -940,12 +913,7 @@ inline Range<const T> MakeRange(const dom::Sequence<T>& seq) {
template <typename T> template <typename T>
inline Range<const T> MakeRange(const RawBuffer<T>& from) { inline Range<const T> MakeRange(const RawBuffer<T>& from) {
return {from.Data(), from.Length()}; return from.Data();
}
template <typename T>
inline Range<T> MakeRange(RawBuffer<T>& from) {
return {from.Data(), from.Length()};
} }
// abv = ArrayBufferView // abv = ArrayBufferView
@@ -964,7 +932,7 @@ Maybe<Range<const uint8_t>> GetRangeFromView(const dom::ArrayBufferView& view,
template <typename T> template <typename T>
RawBuffer<T> RawBufferView(const Range<T>& range) { RawBuffer<T> RawBufferView(const Range<T>& range) {
return {range.length(), range.begin().get()}; return RawBuffer<T>{range};
} }
// - // -
@@ -989,6 +957,16 @@ inline std::string ToString(const nsACString& text) {
return {text.BeginReading(), text.Length()}; return {text.BeginReading(), text.Length()};
} }
inline void Memcpy(const RangedPtr<uint8_t>& destBytes,
const RangedPtr<const uint8_t>& srcBytes,
const size_t byteSize) {
// Trigger range asserts
(void)(srcBytes + byteSize);
(void)(destBytes + byteSize);
memcpy(destBytes.get(), srcBytes.get(), byteSize);
}
// - // -
} // namespace mozilla } // namespace mozilla

View File

@@ -209,11 +209,6 @@ class nsICanvasRenderingContextInternal : public nsISupports,
virtual void OnMemoryPressure() {} virtual void OnMemoryPressure() {}
virtual bool UpdateCompositableHandle(
LayerTransactionChild* aLayerTransaction, CompositableHandle aHandle) {
return false;
}
virtual void OnBeforePaintTransaction() {} virtual void OnBeforePaintTransaction() {}
virtual void OnDidPaintTransaction() {} virtual void OnDidPaintTransaction() {}
virtual mozilla::layers::PersistentBufferProvider* GetBufferProvider() { virtual mozilla::layers::PersistentBufferProvider* GetBufferProvider() {

View File

@@ -51,6 +51,7 @@ void GPUChild::Init() {
devicePrefs.advancedLayers() = gfxConfig::GetValue(Feature::ADVANCED_LAYERS); devicePrefs.advancedLayers() = gfxConfig::GetValue(Feature::ADVANCED_LAYERS);
devicePrefs.useD2D1() = gfxConfig::GetValue(Feature::DIRECT2D); devicePrefs.useD2D1() = gfxConfig::GetValue(Feature::DIRECT2D);
devicePrefs.webGPU() = gfxConfig::GetValue(Feature::WEBGPU); devicePrefs.webGPU() = gfxConfig::GetValue(Feature::WEBGPU);
devicePrefs.d3d11HwAngle() = gfxConfig::GetValue(Feature::D3D11_HW_ANGLE);
nsTArray<LayerTreeIdMapping> mappings; nsTArray<LayerTreeIdMapping> mappings;
LayerTreeOwnerTracker::Get()->Iterate( LayerTreeOwnerTracker::Get()->Iterate(

View File

@@ -187,6 +187,7 @@ mozilla::ipc::IPCResult GPUParent::RecvInit(
gfxConfig::Inherit(Feature::ADVANCED_LAYERS, devicePrefs.advancedLayers()); gfxConfig::Inherit(Feature::ADVANCED_LAYERS, devicePrefs.advancedLayers());
gfxConfig::Inherit(Feature::DIRECT2D, devicePrefs.useD2D1()); gfxConfig::Inherit(Feature::DIRECT2D, devicePrefs.useD2D1());
gfxConfig::Inherit(Feature::WEBGPU, devicePrefs.webGPU()); gfxConfig::Inherit(Feature::WEBGPU, devicePrefs.webGPU());
gfxConfig::Inherit(Feature::D3D11_HW_ANGLE, devicePrefs.d3d11HwAngle());
{ // Let the crash reporter know if we've got WR enabled or not. For other { // Let the crash reporter know if we've got WR enabled or not. For other
// processes this happens in gfxPlatform::InitWebRenderConfig. // processes this happens in gfxPlatform::InitWebRenderConfig.

View File

@@ -35,6 +35,7 @@ struct DevicePrefs
FeatureStatus advancedLayers; FeatureStatus advancedLayers;
FeatureStatus useD2D1; FeatureStatus useD2D1;
FeatureStatus webGPU; FeatureStatus webGPU;
FeatureStatus d3d11HwAngle;
}; };
struct ContentDeviceData struct ContentDeviceData

View File

@@ -53,36 +53,6 @@ struct ParamTraits<mozilla::layers::SharedSurfacesMemoryReport::SurfaceEntry>
: public PlainOldDataSerializer< : public PlainOldDataSerializer<
mozilla::layers::SharedSurfacesMemoryReport::SurfaceEntry> {}; mozilla::layers::SharedSurfacesMemoryReport::SurfaceEntry> {};
template <class KeyType, class DataType>
struct ParamTraits<std::unordered_map<KeyType, DataType>> {
typedef std::unordered_map<KeyType, DataType> paramType;
static void Write(Message* aMsg, const paramType& aParam) {
WriteParam(aMsg, aParam.size());
for (auto i = aParam.begin(); i != aParam.end(); ++i) {
WriteParam(aMsg, i->first);
WriteParam(aMsg, i->second);
}
}
static bool Read(const Message* aMsg, PickleIterator* aIter,
paramType* aResult) {
size_t count;
if (!ReadParam(aMsg, aIter, &count)) {
return false;
}
for (; count > 0; --count) {
KeyType k;
DataType v;
if (!ReadParam(aMsg, aIter, &k) || !ReadParam(aMsg, aIter, &v)) {
return false;
}
aResult->insert(std::make_pair(std::move(k), std::move(v)));
}
return true;
}
};
} // namespace IPC } // namespace IPC
#endif #endif

View File

@@ -16,6 +16,7 @@
#include "mozilla/dom/ipc/StructuredCloneData.h" #include "mozilla/dom/ipc/StructuredCloneData.h"
#include "mozilla/EnumSet.h" #include "mozilla/EnumSet.h"
#include "mozilla/EnumTypeTraits.h" #include "mozilla/EnumTypeTraits.h"
#include "mozilla/IntegerRange.h"
#include "mozilla/Maybe.h" #include "mozilla/Maybe.h"
#include "mozilla/net/WebSocketFrame.h" #include "mozilla/net/WebSocketFrame.h"
#include "mozilla/TimeStamp.h" #include "mozilla/TimeStamp.h"
@@ -28,6 +29,7 @@
#include <limits> #include <limits>
#include <stdint.h> #include <stdint.h>
#include <type_traits> #include <type_traits>
#include <unordered_map>
#include <vector> #include <vector>
#include "nsDebug.h" #include "nsDebug.h"
@@ -797,6 +799,38 @@ struct ParamTraits<std::vector<E>> {
} }
}; };
template <typename K, typename V>
struct ParamTraits<std::unordered_map<K, V>> final {
using T = std::unordered_map<K, V>;
static void Write(Message* const msg, const T& in) {
WriteParam(msg, in.size());
for (const auto& pair : in) {
WriteParam(msg, pair.first);
WriteParam(msg, pair.second);
}
}
static bool Read(const Message* const msg, PickleIterator* const itr,
T* const out) {
size_t size = 0;
if (!ReadParam(msg, itr, &size)) return false;
T map;
map.reserve(size);
for (const auto i : mozilla::IntegerRange(size)) {
std::pair<K, V> pair;
mozilla::Unused << i;
if (!ReadParam(msg, itr, &(pair.first)) ||
!ReadParam(msg, itr, &(pair.second))) {
return false;
}
map.insert(std::move(pair));
}
*out = std::move(map);
return true;
}
};
template <> template <>
struct ParamTraits<float> { struct ParamTraits<float> {
typedef float paramType; typedef float paramType;

View File

@@ -1032,12 +1032,70 @@ description = bug 1363126
description = Synchronous ping allowing worker thread to confirm actor is created. Necessary to avoid racing with ClientHandle actors on main thread. description = Synchronous ping allowing worker thread to confirm actor is created. Necessary to avoid racing with ClientHandle actors on main thread.
[PRemoteSandboxBroker::LaunchApp] [PRemoteSandboxBroker::LaunchApp]
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] # WebGL internals
description = Compositing WebGL is synchronous by spec. Updates to WebGL canvas contents must be updated in lockstep with other DOM updates.
[PWebGL::Initialize] [PWebGL::Initialize]
description = Initialization of WebGL contexts is synchronous by spec. description = Initialization of WebGL contexts is synchronous by spec.
[PWebGL::ExchangeIpdlQueueData] [PWebGL::GetFrontBuffer]
description = Synchronous RPC to allow WebGL to run graphics commands in compositor process and return results to be used in JS return values. description = Publishing a WebGL frame for compositing is synchronous for now to ensure DOM transaction atomicity.
[PWebGL::OnMemoryPressure]
description = Synchronous to ensure immediate memory pressure relief.
# WebGL spec-synchronous functions
[PWebGL::CheckFramebufferStatus]
description = Checking framebuffer completenss must ask the driver.
[PWebGL::ClientWaitSync]
description = Checking fence-sync completenss must ask the driver.
[PWebGL::CreateOpaqueFramebuffer]
description = Must synchronously check for allocation success.
[PWebGL::DrawingBufferSize]
description = The returned size might be smaller than requested due to allocation failure.
[PWebGL::Finish]
description = Synchronous by spec, but not generally used.
[PWebGL::GetBufferSubData]
description = Retrieving buffer contents is synchronous in the worst case.
[PWebGL::GetFrontBufferSnapshot]
description = Retrieving canvas contents is synchronous.
[PWebGL::ReadPixels]
description = Retrieving WebGL framebuffer contents is synchronous.
# WebGL reflection functions
[PWebGL::GetBufferParameter]
description = Reflection is cold code, but synchronous by spec.
[PWebGL::GetCompileResult]
description = Reflection is cold code, but synchronous by spec.
[PWebGL::GetError]
description = Reflection is cold code, but synchronous by spec.
[PWebGL::GetFragDataLocation]
description = Reflection is cold code, but synchronous by spec.
[PWebGL::GetFramebufferAttachmentParameter]
description = Reflection is cold code, but synchronous by spec.
[PWebGL::GetIndexedParameter]
description = Reflection is cold code, but synchronous by spec.
[PWebGL::GetInternalformatParameter]
description = Reflection is cold code, but synchronous by spec.
[PWebGL::GetLinkResult]
description = Reflection is cold code, but synchronous by spec.
[PWebGL::GetNumber]
description = Reflection is cold code, but synchronous by spec.
[PWebGL::GetQueryParameter]
description = Reflection is cold code, but synchronous by spec.
[PWebGL::GetRenderbufferParameter]
description = Reflection is cold code, but synchronous by spec.
[PWebGL::GetSamplerParameter]
description = Reflection is cold code, but synchronous by spec.
[PWebGL::GetShaderPrecisionFormat]
description = Reflection is cold code, but synchronous by spec.
[PWebGL::GetString]
description = Reflection is cold code, but synchronous by spec.
[PWebGL::GetTexParameter]
description = Reflection is cold code, but synchronous by spec.
[PWebGL::GetUniform]
description = Reflection is cold code, but synchronous by spec.
[PWebGL::GetVertexAttrib]
description = Reflection is cold code, but synchronous by spec.
[PWebGL::IsEnabled]
description = Reflection is cold code, but synchronous by spec.
[PWebGL::ValidateProgram]
description = Reflection is cold code, but synchronous by spec.
# -
[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.

View File

@@ -18,6 +18,11 @@ namespace mozilla {
// Range<T> is a tuple containing a pointer and a length. // Range<T> is a tuple containing a pointer and a length.
template <typename T> template <typename T>
class Range { class Range {
template <typename U>
friend class Range;
// Reassignment of RangedPtrs is so (subtly) restrictive that we just make
// Range immutable.
const RangedPtr<T> mStart; const RangedPtr<T> mStart;
const RangedPtr<T> mEnd; const RangedPtr<T> mEnd;

View File

@@ -42,6 +42,9 @@ namespace mozilla {
*/ */
template <typename T> template <typename T>
class RangedPtr { class RangedPtr {
template <typename U>
friend class RangedPtr;
T* mPtr; T* mPtr;
#ifdef DEBUG #ifdef DEBUG
@@ -119,7 +122,19 @@ class RangedPtr {
checkSanity(); checkSanity();
} }
MOZ_IMPLICIT RangedPtr(const RangedPtr<T>& aOther) RangedPtr(const RangedPtr& aOther)
: mPtr(aOther.mPtr)
#ifdef DEBUG
,
mRangeStart(aOther.mRangeStart),
mRangeEnd(aOther.mRangeEnd)
#endif
{
checkSanity();
}
template <typename U>
MOZ_IMPLICIT RangedPtr(const RangedPtr<U>& aOther)
: mPtr(aOther.mPtr) : mPtr(aOther.mPtr)
#ifdef DEBUG #ifdef DEBUG
, ,

View File

@@ -20,5 +20,10 @@ void test_RangeToBoolConversionShouldCompile() {
(void)dummy; (void)dummy;
} }
void test_RangeT_To_RangeConstT_ShouldCompile() {
auto dummy = Range<const int>{Range<int>{}};
(void)dummy;
}
// We need a proper program so we have someplace to hang the static_asserts. // We need a proper program so we have someplace to hang the static_asserts.
int main() { return 0; } int main() { return 0; }

View File

@@ -9634,7 +9634,7 @@
mirror: always mirror: always
- name: webgl.force-layers-readback - name: webgl.force-layers-readback
type: bool type: RelaxedAtomicBool
value: false value: false
mirror: always mirror: always
@@ -9684,14 +9684,14 @@
mirror: always mirror: always
- name: webgl.power-preference-override - name: webgl.power-preference-override
type: int32_t type: RelaxedAtomicInt32
value: 0 value: 0
mirror: always mirror: always
- name: webgl.prefer-16bpp - name: webgl.prefer-16bpp
type: bool type: RelaxedAtomicBool
value: false value: false
mirror: never mirror: always
- name: webgl.allow-immediate-queries - name: webgl.allow-immediate-queries
type: RelaxedAtomicBool type: RelaxedAtomicBool
@@ -9719,10 +9719,9 @@
value: true value: true
mirror: always mirror: always
# value is 0 for PCQ, 1 for Ipdl - name: webgl.oop.via-pcq
- name: webgl.prototype.ipc-pcq type: RelaxedAtomicBool
type: uint32_t value: false
value: 0
mirror: always mirror: always
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------

View File

@@ -19,7 +19,7 @@ Classes = [
'type': 'mozilla::widget::ScreenManager', 'type': 'mozilla::widget::ScreenManager',
'constructor': 'mozilla::widget::ScreenManager::GetAddRefedSingleton', 'constructor': 'mozilla::widget::ScreenManager::GetAddRefedSingleton',
'headers': ['/widget/ScreenManager.h'], 'headers': ['/widget/ScreenManager.h'],
'processes': ProcessSelector.MAIN_PROCESS_ONLY, 'processes': ProcessSelector.ALLOW_IN_GPU_AND_MAIN_PROCESS,
}, },
{ {
'cid': '{2d96b3df-c051-11d1-a827-0040959a28c9}', 'cid': '{2d96b3df-c051-11d1-a827-0040959a28c9}',

View File

@@ -54,6 +54,7 @@ struct Module {
ALLOW_IN_VR_PROCESS = 0x8, ALLOW_IN_VR_PROCESS = 0x8,
ALLOW_IN_SOCKET_PROCESS = 0x10, ALLOW_IN_SOCKET_PROCESS = 0x10,
ALLOW_IN_RDD_PROCESS = 0x20, ALLOW_IN_RDD_PROCESS = 0x20,
ALLOW_IN_GPU_AND_MAIN_PROCESS = ALLOW_IN_GPU_PROCESS | MAIN_PROCESS_ONLY,
ALLOW_IN_GPU_AND_VR_PROCESS = ALLOW_IN_GPU_PROCESS | ALLOW_IN_VR_PROCESS, ALLOW_IN_GPU_AND_VR_PROCESS = ALLOW_IN_GPU_PROCESS | ALLOW_IN_VR_PROCESS,
ALLOW_IN_GPU_AND_SOCKET_PROCESS = ALLOW_IN_GPU_AND_SOCKET_PROCESS =
ALLOW_IN_GPU_PROCESS | ALLOW_IN_SOCKET_PROCESS, ALLOW_IN_GPU_PROCESS | ALLOW_IN_SOCKET_PROCESS,

View File

@@ -63,6 +63,8 @@ class ProcessSelector:
ALLOW_IN_VR_PROCESS = 0x8 ALLOW_IN_VR_PROCESS = 0x8
ALLOW_IN_SOCKET_PROCESS = 0x10 ALLOW_IN_SOCKET_PROCESS = 0x10
ALLOW_IN_RDD_PROCESS = 0x20 ALLOW_IN_RDD_PROCESS = 0x20
ALLOW_IN_GPU_AND_MAIN_PROCESS = (ALLOW_IN_GPU_PROCESS |
MAIN_PROCESS_ONLY)
ALLOW_IN_GPU_AND_SOCKET_PROCESS = (ALLOW_IN_GPU_PROCESS | ALLOW_IN_GPU_AND_SOCKET_PROCESS = (ALLOW_IN_GPU_PROCESS |
ALLOW_IN_SOCKET_PROCESS) ALLOW_IN_SOCKET_PROCESS)
ALLOW_IN_GPU_AND_VR_PROCESS = ALLOW_IN_GPU_PROCESS | ALLOW_IN_VR_PROCESS ALLOW_IN_GPU_AND_VR_PROCESS = ALLOW_IN_GPU_PROCESS | ALLOW_IN_VR_PROCESS
@@ -90,6 +92,7 @@ PROCESSES = {
ProcessSelector.ALLOW_IN_VR_PROCESS: 'ALLOW_IN_VR_PROCESS', ProcessSelector.ALLOW_IN_VR_PROCESS: 'ALLOW_IN_VR_PROCESS',
ProcessSelector.ALLOW_IN_SOCKET_PROCESS: 'ALLOW_IN_SOCKET_PROCESS', ProcessSelector.ALLOW_IN_SOCKET_PROCESS: 'ALLOW_IN_SOCKET_PROCESS',
ProcessSelector.ALLOW_IN_RDD_PROCESS: 'ALLOW_IN_RDD_PROCESS', ProcessSelector.ALLOW_IN_RDD_PROCESS: 'ALLOW_IN_RDD_PROCESS',
ProcessSelector.ALLOW_IN_GPU_AND_MAIN_PROCESS: 'ALLOW_IN_GPU_AND_MAIN_PROCESS',
ProcessSelector.ALLOW_IN_GPU_AND_SOCKET_PROCESS: 'ALLOW_IN_GPU_AND_SOCKET_PROCESS', ProcessSelector.ALLOW_IN_GPU_AND_SOCKET_PROCESS: 'ALLOW_IN_GPU_AND_SOCKET_PROCESS',
ProcessSelector.ALLOW_IN_GPU_AND_VR_PROCESS: 'ALLOW_IN_GPU_AND_VR_PROCESS', ProcessSelector.ALLOW_IN_GPU_AND_VR_PROCESS: 'ALLOW_IN_GPU_AND_VR_PROCESS',
ProcessSelector.ALLOW_IN_GPU_VR_AND_SOCKET_PROCESS: 'ALLOW_IN_GPU_VR_AND_SOCKET_PROCESS', ProcessSelector.ALLOW_IN_GPU_VR_AND_SOCKET_PROCESS: 'ALLOW_IN_GPU_VR_AND_SOCKET_PROCESS',

View File

@@ -395,6 +395,8 @@ nsresult nsComponentManagerImpl::Init() {
ProcessSelectorMatches(ProcessSelector::ALLOW_IN_SOCKET_PROCESS); ProcessSelectorMatches(ProcessSelector::ALLOW_IN_SOCKET_PROCESS);
gProcessMatchTable[size_t(ProcessSelector::ALLOW_IN_RDD_PROCESS)] = gProcessMatchTable[size_t(ProcessSelector::ALLOW_IN_RDD_PROCESS)] =
ProcessSelectorMatches(ProcessSelector::ALLOW_IN_RDD_PROCESS); ProcessSelectorMatches(ProcessSelector::ALLOW_IN_RDD_PROCESS);
gProcessMatchTable[size_t(ProcessSelector::ALLOW_IN_GPU_AND_MAIN_PROCESS)] =
ProcessSelectorMatches(ProcessSelector::ALLOW_IN_GPU_AND_MAIN_PROCESS);
gProcessMatchTable[size_t(ProcessSelector::ALLOW_IN_GPU_AND_VR_PROCESS)] = gProcessMatchTable[size_t(ProcessSelector::ALLOW_IN_GPU_AND_VR_PROCESS)] =
ProcessSelectorMatches(ProcessSelector::ALLOW_IN_GPU_AND_VR_PROCESS); ProcessSelectorMatches(ProcessSelector::ALLOW_IN_GPU_AND_VR_PROCESS);
gProcessMatchTable[size_t( gProcessMatchTable[size_t(