Bug 1700051: part 26) Correct typo in comment of `mozInlineSpellWordUtil::BuildSoftTe...
[gecko.git] / dom / canvas / WebGLCommandQueue.h
blob8331f49c262b4532a5ebcc8be160c91a9bbc3ad8
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_
9 #include <type_traits>
10 #include "mozilla/FunctionTypeTraits.h"
11 #include "mozilla/ipc/IPDLParamTraits.h"
12 #include "QueueParamTraits.h"
13 #include "WebGLTypes.h"
15 namespace mozilla {
17 using webgl::QueueStatus;
19 namespace webgl {
21 class RangeConsumerView final : public webgl::ConsumerView<RangeConsumerView> {
22 RangedPtr<const uint8_t> mSrcItr;
23 const RangedPtr<const uint8_t> mSrcEnd;
25 public:
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()) {
38 mSrcItr = mSrcEnd;
39 return;
41 mSrcItr += offset;
44 template <typename T>
45 Maybe<Range<const T>> ReadRange(const size_t elemCount) {
46 AlignTo(alignof(T));
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());
57 mSrcItr += byteSize;
58 return Some(Range<const T>{begin, elemCount});
62 // -
64 namespace details {
66 class SizeOnlyProducerView final
67 : public webgl::ProducerView<SizeOnlyProducerView> {
68 size_t mRequiredSize = 0;
70 public:
71 SizeOnlyProducerView() : ProducerView(this, 0, nullptr) {}
73 template <typename T>
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; }
88 // -
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;
95 public:
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());
113 mDestItr += offset;
115 MOZ_ASSERT(byteSize <= Remaining());
116 if (byteSize) {
117 memcpy(mDestItr.get(), src.begin().get(), byteSize);
119 mDestItr += byteSize;
123 // -
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
137 // -
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...);
152 // -
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...);
162 } // namespace webgl
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.
170 // Example:
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.
178 // Example:
179 // template <>
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.
186 // Example:
187 // int result = Run<MyClass::MyMethod>(param1, std::move(param2));
189 template <template <size_t> typename Derived>
190 class EmptyMethodDispatcher {
191 public:
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");
199 // -
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,
215 MethodType method>
216 class MethodDispatcher {
217 static constexpr size_t kId = ID;
218 using DerivedType = Derived<ID>;
219 using NextDispatcher = Derived<ID + 1>;
221 public:
222 template <typename ObjectT>
223 static MOZ_ALWAYS_INLINE bool DispatchCommand(
224 ObjectT& obj, const size_t id, webgl::RangeConsumerView& view) {
225 if (id == kId) {
226 auto argsTuple = ArgsTuple(method);
228 return std::apply(
229 [&](auto&... args) {
230 if (!webgl::Deserialize(view, args...)) return false;
231 (obj.*method)(args...);
232 return true;
234 argsTuple);
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_