1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef WEBGLCOMMANDQUEUE_H_
7 #define WEBGLCOMMANDQUEUE_H_
10 #include "mozilla/FunctionTypeTraits.h"
11 #include "mozilla/ipc/IPDLParamTraits.h"
12 #include "QueueParamTraits.h"
13 #include "WebGLTypes.h"
17 using webgl::QueueStatus
;
21 class RangeConsumerView final
: public webgl::ConsumerView
<RangeConsumerView
> {
22 RangedPtr
<const uint8_t> mSrcItr
;
23 const RangedPtr
<const uint8_t> mSrcEnd
;
26 auto Remaining() const { return *MaybeAs
<size_t>(mSrcEnd
- mSrcItr
); }
28 explicit RangeConsumerView(const Range
<const uint8_t> range
)
29 : ConsumerView(this, nullptr, 0),
30 mSrcItr(range
.begin()),
31 mSrcEnd(range
.end()) {
32 (void)Remaining(); // assert size non-negative
35 void AlignTo(const size_t alignment
) {
36 const auto offset
= AlignmentOffset(alignment
, mSrcItr
.get());
37 if (offset
> Remaining()) {
45 Maybe
<Range
<const T
>> ReadRange(const size_t elemCount
) {
48 constexpr auto elemSize
= sizeof(T
);
49 const auto byteSizeChecked
= CheckedInt
<size_t>(elemCount
) * elemSize
;
50 MOZ_RELEASE_ASSERT(byteSizeChecked
.isValid());
51 const auto& byteSize
= byteSizeChecked
.value();
53 const auto remaining
= Remaining();
54 if (byteSize
> remaining
) return {};
56 const auto begin
= reinterpret_cast<const T
*>(mSrcItr
.get());
58 return Some(Range
<const T
>{begin
, elemCount
});
66 class SizeOnlyProducerView final
67 : public webgl::ProducerView
<SizeOnlyProducerView
> {
68 size_t mRequiredSize
= 0;
71 SizeOnlyProducerView() : ProducerView(this, 0, nullptr) {}
74 void WriteFromRange(const Range
<const T
>& src
) {
75 constexpr auto alignment
= alignof(T
);
76 const size_t byteSize
= ByteSize(src
);
77 // printf_stderr("SizeOnlyProducerView: @%zu +%zu\n", alignment, byteSize);
79 const auto offset
= AlignmentOffset(alignment
, mRequiredSize
);
80 mRequiredSize
+= offset
;
82 mRequiredSize
+= byteSize
;
85 const auto& RequiredSize() const { return mRequiredSize
; }
90 class RangeProducerView final
: public webgl::ProducerView
<RangeProducerView
> {
91 const RangedPtr
<uint8_t> mDestBegin
;
92 const RangedPtr
<uint8_t> mDestEnd
;
93 RangedPtr
<uint8_t> mDestItr
;
96 auto Remaining() const { return *MaybeAs
<size_t>(mDestEnd
- mDestItr
); }
98 explicit RangeProducerView(const Range
<uint8_t> range
)
99 : ProducerView(this, 0, nullptr),
100 mDestBegin(range
.begin()),
101 mDestEnd(range
.end()),
102 mDestItr(mDestBegin
) {
103 (void)Remaining(); // assert size non-negative
106 template <typename T
>
107 void WriteFromRange(const Range
<const T
>& src
) {
108 constexpr auto alignment
= alignof(T
);
109 const size_t byteSize
= ByteSize(src
);
110 // printf_stderr("RangeProducerView: @%zu +%zu\n", alignment, byteSize);
112 const auto offset
= AlignmentOffset(alignment
, mDestItr
.get());
115 MOZ_ASSERT(byteSize
<= Remaining());
117 memcpy(mDestItr
.get(), src
.begin().get(), byteSize
);
119 mDestItr
+= byteSize
;
125 template <typename ProducerViewT
>
126 inline void Serialize(ProducerViewT
&) {}
128 template <typename ProducerViewT
, typename Arg
, typename
... Args
>
129 inline void Serialize(ProducerViewT
& view
, const Arg
& arg
,
130 const Args
&... args
) {
131 MOZ_ALWAYS_TRUE(view
.WriteParam(arg
) == QueueStatus::kSuccess
);
132 Serialize(view
, args
...);
135 } // namespace details
139 template <typename
... Args
>
140 size_t SerializedSize(const Args
&... args
) {
141 webgl::details::SizeOnlyProducerView sizeView
;
142 webgl::details::Serialize(sizeView
, args
...);
143 return sizeView
.RequiredSize();
146 template <typename
... Args
>
147 void Serialize(Range
<uint8_t> dest
, const Args
&... args
) {
148 webgl::details::RangeProducerView
view(dest
);
149 webgl::details::Serialize(view
, args
...);
154 inline bool Deserialize(RangeConsumerView
& view
) { return true; }
156 template <typename Arg
, typename
... Args
>
157 inline bool Deserialize(RangeConsumerView
& view
, Arg
& arg
, Args
&... args
) {
158 if (!webgl::QueueParamTraits
<Arg
>::Read(view
, &arg
)) return false;
159 return Deserialize(view
, args
...);
164 // The MethodDispatcher setup uses a CommandSink to read parameters, call the
165 // given method using the given synchronization protocol, and provide
166 // compile-time lookup of the ID by class method.
167 // To use this system, first define a dispatcher subclass of
168 // EmptyMethodDispatcher. This class must be parameterized by command ID.
171 // template <size_t id=0> class MyDispatcher
172 // : public EmptyMethodDispatcher<MyDispatcher> {};
174 // Then, for each command handled, specialize this to subclass MethodDispatcher.
175 // The subclass must define the Method. It may optionally define isSync for
176 // synchronous methods.
180 // class MyDispatcher<0>
181 // : public MethodDispatcher<MyDispatcher, 0,
182 // decltype(&MyClass::MyMethod), MyClass::MyMethod> {};
184 // The method may then be called from the source and run on the sink.
187 // int result = Run<MyClass::MyMethod>(param1, std::move(param2));
189 template <template <size_t> typename Derived
>
190 class EmptyMethodDispatcher
{
192 template <typename ObjectT
>
193 static MOZ_ALWAYS_INLINE
bool DispatchCommand(ObjectT
&, const size_t,
194 webgl::RangeConsumerView
&) {
195 MOZ_CRASH("Illegal ID in DispatchCommand");
201 template <typename ReturnT
, typename ObjectT
, typename
... Args
>
202 std::tuple
<std::remove_cv_t
<std::remove_reference_t
<Args
>>...> ArgsTuple(
203 ReturnT (ObjectT::*)(Args
... args
)) {
204 return std::tuple
<std::remove_cv_t
<std::remove_reference_t
<Args
>>...>{};
207 template <typename ReturnT
, typename ObjectT
, typename
... Args
>
208 std::tuple
<std::remove_cv_t
<std::remove_reference_t
<Args
>>...> ArgsTuple(
209 ReturnT (ObjectT::*)(Args
... args
) const) {
210 return std::tuple
<std::remove_cv_t
<std::remove_reference_t
<Args
>>...>{};
213 // Derived type must be parameterized by the ID.
214 template <template <size_t> typename Derived
, size_t ID
, typename MethodType
,
216 class MethodDispatcher
{
217 static constexpr size_t kId
= ID
;
218 using DerivedType
= Derived
<ID
>;
219 using NextDispatcher
= Derived
<ID
+ 1>;
222 template <typename ObjectT
>
223 static MOZ_ALWAYS_INLINE
bool DispatchCommand(
224 ObjectT
& obj
, const size_t id
, webgl::RangeConsumerView
& view
) {
226 auto argsTuple
= ArgsTuple(method
);
230 if (!webgl::Deserialize(view
, args
...)) return false;
231 (obj
.*method
)(args
...);
236 return Derived
<kId
+ 1>::DispatchCommand(obj
, id
, view
);
239 static constexpr size_t Id() { return kId
; }
240 static constexpr MethodType
Method() { return method
; }
243 } // namespace mozilla
245 #endif // WEBGLCOMMANDQUEUE_H_