/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef WEBGLIPDL_H_ #define WEBGLIPDL_H_ #include "gfxTypes.h" #include "ipc/EnumSerializer.h" #include "ipc/IPCMessageUtils.h" #include "mozilla/GfxMessageUtils.h" #include "mozilla/dom/BindingIPCUtils.h" #include "mozilla/ipc/IPDLParamTraits.h" #include "mozilla/ipc/Shmem.h" #include "mozilla/layers/LayersSurfaces.h" #include "TiedFields.h" #include "TupleUtils.h" #include "WebGLTypes.h" namespace mozilla { namespace webgl { // TODO: This should probably replace Shmem, or at least this should move to // ipc/glue. class RaiiShmem final { RefPtr mWeakRef; mozilla::ipc::Shmem mShmem = {}; public: /// Returns zeroed data. static RaiiShmem Alloc(mozilla::ipc::IProtocol* const allocator, const size_t size) { mozilla::ipc::Shmem shmem; if (!allocator->AllocShmem(size, &shmem)) return {}; return {allocator, shmem}; } static RaiiShmem AllocUnsafe(mozilla::ipc::IProtocol* const allocator, const size_t size) { mozilla::ipc::Shmem shmem; if (!allocator->AllocUnsafeShmem(size, &shmem)) return {}; return {allocator, shmem}; } // - RaiiShmem() = default; RaiiShmem(mozilla::ipc::IProtocol* const allocator, const mozilla::ipc::Shmem& shmem) { if (!allocator || !allocator->CanSend()) { return; } // Shmems are handled by the top-level, so use that or we might leak after // the actor dies. mWeakRef = allocator->ToplevelProtocol()->GetLifecycleProxy(); mShmem = shmem; if (!mWeakRef || !mWeakRef->Get() || !IsShmem()) { reset(); } } void reset() { if (IsShmem()) { const auto& allocator = mWeakRef->Get(); if (allocator) { allocator->DeallocShmem(mShmem); } } mWeakRef = nullptr; mShmem = {}; } ~RaiiShmem() { reset(); } // - RaiiShmem(RaiiShmem&& rhs) { *this = std::move(rhs); } RaiiShmem& operator=(RaiiShmem&& rhs) { reset(); mWeakRef = rhs.mWeakRef; mShmem = rhs.Extract(); return *this; } // - bool IsShmem() const { return mShmem.IsReadable(); } explicit operator bool() const { return IsShmem(); } // - const auto& Shmem() const { MOZ_ASSERT(IsShmem()); return mShmem; } Range ByteRange() const { if (!IsShmem()) { return {}; } return {mShmem.get(), mShmem.Size()}; } mozilla::ipc::Shmem Extract() { auto ret = mShmem; mShmem = {}; reset(); return ret; } }; using Int32Vector = std::vector; } // namespace webgl namespace ipc { template <> struct IPDLParamTraits final { using T = mozilla::webgl::FrontBufferSnapshotIpc; static void Write(IPC::MessageWriter* const writer, IProtocol* actor, T& in) { WriteParam(writer, in.surfSize); WriteIPDLParam(writer, actor, std::move(in.shmem)); } static bool Read(IPC::MessageReader* const reader, IProtocol* actor, T* const out) { return ReadParam(reader, &out->surfSize) && ReadIPDLParam(reader, actor, &out->shmem); } }; // - template <> struct IPDLParamTraits final { using T = mozilla::webgl::ReadPixelsResultIpc; static void Write(IPC::MessageWriter* const writer, IProtocol* actor, T& in) { WriteParam(writer, in.subrect); WriteParam(writer, in.byteStride); WriteIPDLParam(writer, actor, std::move(in.shmem)); } static bool Read(IPC::MessageReader* const reader, IProtocol* actor, T* const out) { return ReadParam(reader, &out->subrect) && ReadParam(reader, &out->byteStride) && ReadIPDLParam(reader, actor, &out->shmem); } }; // - template <> struct IPDLParamTraits final { using T = mozilla::webgl::TexUnpackBlobDesc; static void Write(IPC::MessageWriter* const writer, IProtocol* actor, T&& in) { WriteParam(writer, in.imageTarget); WriteParam(writer, in.size); WriteParam(writer, in.srcAlphaType); MOZ_RELEASE_ASSERT(!in.cpuData); MOZ_RELEASE_ASSERT(!in.pboOffset); WriteParam(writer, in.structuredSrcSize); MOZ_RELEASE_ASSERT(!in.image); WriteIPDLParam(writer, actor, std::move(in.sd)); MOZ_RELEASE_ASSERT(!in.dataSurf); WriteParam(writer, in.unpacking); WriteParam(writer, in.applyUnpackTransforms); } static bool Read(IPC::MessageReader* const reader, IProtocol* actor, T* const out) { return ReadParam(reader, &out->imageTarget) && ReadParam(reader, &out->size) && ReadParam(reader, &out->srcAlphaType) && ReadParam(reader, &out->structuredSrcSize) && ReadIPDLParam(reader, actor, &out->sd) && ReadParam(reader, &out->unpacking) && ReadParam(reader, &out->applyUnpackTransforms); } }; } // namespace ipc namespace webgl { using Int32Vector = std::vector; } // namespace webgl } // namespace mozilla namespace IPC { // - template struct ParamTraits> final { using T = mozilla::webgl::Padded; static void Write(MessageWriter* const writer, const T& in) { WriteParam(writer, *in); } static bool Read(MessageReader* const reader, T* const out) { return ReadParam(reader, &**out); } }; // - template <> struct ParamTraits : public ContiguousEnumSerializerInclusive< mozilla::webgl::AttribBaseType, mozilla::webgl::AttribBaseType::Boolean, mozilla::webgl::AttribBaseType::Uint> {}; template <> struct ParamTraits : public ContiguousEnumSerializerInclusive< mozilla::webgl::ContextLossReason, mozilla::webgl::ContextLossReason::None, mozilla::webgl::ContextLossReason::Guilty> {}; template <> struct ParamTraits : public ContiguousEnumSerializerInclusive< gfxAlphaType, gfxAlphaType::Opaque, gfxAlphaType::NonPremult> {}; template <> struct ParamTraits final : public mozilla::dom::WebIDLEnumSerializer< mozilla::dom::WebGLPowerPreference> {}; template <> struct ParamTraits final : public mozilla::dom::WebIDLEnumSerializer< mozilla::dom::PredefinedColorSpace> {}; // - // ParamTraits_TiedFields template struct ParamTraits_TiedFields { static_assert(mozilla::AssertTiedFieldsAreExhaustive()); static void Write(MessageWriter* const writer, const T& in) { const auto& fields = mozilla::TiedFields(in); mozilla::MapTuple(fields, [&](const auto& field) { WriteParam(writer, field); return true; // ignored }); } static bool Read(MessageReader* const reader, T* const out) { const auto& fields = mozilla::TiedFields(*out); bool ok = true; mozilla::MapTuple(fields, [&](auto& field) { if (ok) { ok &= ReadParam(reader, &field); } return true; // ignored }); return ok; } }; // - template <> struct ParamTraits final : public ParamTraits_TiedFields {}; template <> struct ParamTraits final : public ParamTraits_TiedFields {}; template <> struct ParamTraits final : public ParamTraits_TiedFields { }; // - template <> struct ParamTraits : public ContiguousEnumSerializerInclusive { }; template struct ParamTraits> final : public ParamTraits_TiedFields> {}; template <> struct ParamTraits final : public ParamTraits_TiedFields {}; template <> struct ParamTraits final : public ParamTraits_TiedFields {}; template <> struct ParamTraits final : public ParamTraits_TiedFields {}; template <> struct ParamTraits final : public ParamTraits_TiedFields {}; // - template <> struct ParamTraits final { using T = mozilla::webgl::ReadPixelsDesc; static void Write(MessageWriter* const writer, const T& in) { WriteParam(writer, in.srcOffset); WriteParam(writer, in.size); WriteParam(writer, in.pi); WriteParam(writer, in.packState); } static bool Read(MessageReader* const reader, T* const out) { return ReadParam(reader, &out->srcOffset) && ReadParam(reader, &out->size) && ReadParam(reader, &out->pi) && ReadParam(reader, &out->packState); } }; // - template <> struct ParamTraits final { using T = mozilla::webgl::PackingInfo; static void Write(MessageWriter* const writer, const T& in) { WriteParam(writer, in.format); WriteParam(writer, in.type); } static bool Read(MessageReader* const reader, T* const out) { return ReadParam(reader, &out->format) && ReadParam(reader, &out->type); } }; // - template <> struct ParamTraits final { using T = mozilla::webgl::CompileResult; static void Write(MessageWriter* const writer, const T& in) { WriteParam(writer, in.pending); WriteParam(writer, in.log); WriteParam(writer, in.translatedSource); WriteParam(writer, in.success); } static bool Read(MessageReader* const reader, T* const out) { return ReadParam(reader, &out->pending) && ReadParam(reader, &out->log) && ReadParam(reader, &out->translatedSource) && ReadParam(reader, &out->success); } }; // - template <> struct ParamTraits final { using T = mozilla::webgl::LinkResult; static void Write(MessageWriter* const writer, const T& in) { WriteParam(writer, in.pending); WriteParam(writer, in.log); WriteParam(writer, in.success); WriteParam(writer, in.active); WriteParam(writer, in.tfBufferMode); } static bool Read(MessageReader* const reader, T* const out) { return ReadParam(reader, &out->pending) && ReadParam(reader, &out->log) && ReadParam(reader, &out->success) && ReadParam(reader, &out->active) && ReadParam(reader, &out->tfBufferMode); } }; // - template <> struct ParamTraits final { using T = mozilla::webgl::LinkActiveInfo; static void Write(MessageWriter* const writer, const T& in) { WriteParam(writer, in.activeAttribs); WriteParam(writer, in.activeUniforms); WriteParam(writer, in.activeUniformBlocks); WriteParam(writer, in.activeTfVaryings); } static bool Read(MessageReader* const reader, T* const out) { return ReadParam(reader, &out->activeAttribs) && ReadParam(reader, &out->activeUniforms) && ReadParam(reader, &out->activeUniformBlocks) && ReadParam(reader, &out->activeTfVaryings); } }; // - template <> struct ParamTraits final { using T = mozilla::webgl::ActiveInfo; static void Write(MessageWriter* const writer, const T& in) { WriteParam(writer, in.elemType); WriteParam(writer, in.elemCount); WriteParam(writer, in.name); } static bool Read(MessageReader* const reader, T* const out) { return ReadParam(reader, &out->elemType) && ReadParam(reader, &out->elemCount) && ReadParam(reader, &out->name); } }; // - template <> struct ParamTraits final { using T = mozilla::webgl::ActiveAttribInfo; static void Write(MessageWriter* const writer, const T& in) { WriteParam(writer, static_cast(in)); WriteParam(writer, in.location); WriteParam(writer, in.baseType); } static bool Read(MessageReader* const reader, T* const out) { return ReadParam(reader, static_cast(out)) && ReadParam(reader, &out->location) && ReadParam(reader, &out->baseType); } }; // - template <> struct ParamTraits final { using T = mozilla::webgl::ActiveUniformInfo; static void Write(MessageWriter* const writer, const T& in) { WriteParam(writer, static_cast(in)); WriteParam(writer, in.locByIndex); WriteParam(writer, in.block_index); WriteParam(writer, in.block_offset); WriteParam(writer, in.block_arrayStride); WriteParam(writer, in.block_matrixStride); WriteParam(writer, in.block_isRowMajor); } static bool Read(MessageReader* const reader, T* const out) { return ReadParam(reader, static_cast(out)) && ReadParam(reader, &out->locByIndex) && ReadParam(reader, &out->block_index) && ReadParam(reader, &out->block_offset) && ReadParam(reader, &out->block_arrayStride) && ReadParam(reader, &out->block_matrixStride) && ReadParam(reader, &out->block_isRowMajor); } }; // - template <> struct ParamTraits final { using T = mozilla::webgl::ActiveUniformBlockInfo; static void Write(MessageWriter* const writer, const T& in) { WriteParam(writer, in.name); WriteParam(writer, in.dataSize); WriteParam(writer, in.activeUniformIndices); WriteParam(writer, in.referencedByVertexShader); WriteParam(writer, in.referencedByFragmentShader); } static bool Read(MessageReader* const reader, T* const out) { return ReadParam(reader, &out->name) && ReadParam(reader, &out->dataSize) && ReadParam(reader, &out->activeUniformIndices) && ReadParam(reader, &out->referencedByVertexShader) && ReadParam(reader, &out->referencedByFragmentShader); } }; // - template <> struct ParamTraits final { using T = mozilla::webgl::ShaderPrecisionFormat; static void Write(MessageWriter* const writer, const T& in) { WriteParam(writer, in.rangeMin); WriteParam(writer, in.rangeMax); WriteParam(writer, in.precision); } static bool Read(MessageReader* const reader, T* const out) { return ReadParam(reader, &out->rangeMin) && ReadParam(reader, &out->rangeMax) && ReadParam(reader, &out->precision); } }; // - template struct ParamTraits> final { using T = std::array; static void Write(MessageWriter* const writer, const T& in) { for (const auto& v : in) { WriteParam(writer, v); } } static bool Read(MessageReader* const reader, T* const out) { for (auto& v : *out) { if (!ReadParam(reader, &v)) return false; } return true; } }; template struct ParamTraits final { using T = U[N]; static constexpr size_t kByteSize = sizeof(U) * N; static_assert(std::is_trivial::value); static void Write(MessageWriter* const writer, const T& in) { writer->WriteBytes(in, kByteSize); } static bool Read(MessageReader* const reader, T* const out) { if (!reader->HasBytesAvailable(kByteSize)) { return false; } return reader->ReadBytesInto(*out, kByteSize); } }; // - template <> struct ParamTraits final { using T = mozilla::webgl::GetUniformData; static void Write(MessageWriter* const writer, const T& in) { ParamTraits::Write(writer, in.data); WriteParam(writer, in.type); } static bool Read(MessageReader* const reader, T* const out) { return ParamTraitsdata)>::Read(reader, &out->data) && ReadParam(reader, &out->type); } }; // - template struct ParamTraits> final { using T = mozilla::avec2; static void Write(MessageWriter* const writer, const T& in) { WriteParam(writer, in.x); WriteParam(writer, in.y); } static bool Read(MessageReader* const reader, T* const out) { return ReadParam(reader, &out->x) && ReadParam(reader, &out->y); } }; // - template struct ParamTraits> final { using T = mozilla::avec3; static void Write(MessageWriter* const writer, const T& in) { WriteParam(writer, in.x); WriteParam(writer, in.y); WriteParam(writer, in.z); } static bool Read(MessageReader* const reader, T* const out) { return ReadParam(reader, &out->x) && ReadParam(reader, &out->y) && ReadParam(reader, &out->z); } }; // - template struct ParamTraits_IsEnumCase { using T = TT; static void Write(IPC::MessageWriter* const writer, const T& in) { MOZ_RELEASE_ASSERT(IsEnumCase(in)); WriteParam(writer, mozilla::UnderlyingValue(in)); } static bool Read(IPC::MessageReader* const reader, T* const out) { std::underlying_type_t rawVal; if (!ReadParam(reader, &rawVal)) return false; *out = static_cast(rawVal); return IsEnumCase(*out); } }; // - #define USE_IS_ENUM_CASE(T) \ template <> \ struct ParamTraits : public ParamTraits_IsEnumCase {}; USE_IS_ENUM_CASE(mozilla::webgl::OptionalRenderableFormatBits) #undef USE_IS_ENUM_CASE } // namespace IPC #endif