• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2010 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #ifndef BufferWriter_DEFINED
9 #define BufferWriter_DEFINED
10 
11 #include "include/core/SkRect.h"
12 #include "include/private/SkNx.h"
13 #include "include/private/SkTemplates.h"
14 #include <type_traits>
15 
16 namespace skgpu {
17 
18 struct BufferWriter {
19 public:
20     operator bool() const { return fPtr != nullptr; }
21 
22 protected:
23     BufferWriter() = default;
BufferWriterBufferWriter24     BufferWriter(void* ptr) : fPtr(ptr) {}
25 
26     BufferWriter& operator=(const BufferWriter&) = delete;
27     BufferWriter& operator=(BufferWriter&& that) {
28         fPtr = that.fPtr;
29         that.fPtr = nullptr;
30         return *this;
31     }
32 
33 protected:
34     void* fPtr;
35 };
36 
37 /**
38  * Helper for writing vertex data to a buffer. Usage:
39  *  VertexWriter vertices{target->makeVertexSpace(...)};
40  *  vertices << A0 << B0 << C0 << ...;
41  *  vertices << A1 << B1 << C1 << ...;
42  *
43  * Each value must be POD (plain old data), or have a specialization of the "<<" operator.
44  */
45 struct VertexWriter : public BufferWriter {
46     inline constexpr static uint32_t kIEEE_32_infinity = 0x7f800000;
47 
48     VertexWriter() = default;
VertexWriterVertexWriter49     VertexWriter(void* ptr) : BufferWriter(ptr) {}
50     VertexWriter(const VertexWriter&) = delete;
VertexWriterVertexWriter51     VertexWriter(VertexWriter&& that) { *this = std::move(that); }
52 
53     VertexWriter& operator=(const VertexWriter&) = delete;
54     VertexWriter& operator=(VertexWriter&& that) {
55         BufferWriter::operator=(std::move(that));
56         return *this;
57     }
58 
59     bool operator==(const VertexWriter& that) const { return fPtr == that.fPtr; }
60 
61     // TODO: Remove this call. We want all users of VertexWriter to have to go through the vertex
62     // writer functions to write data. We do not want them to directly access fPtr and copy their
63     // own data.
ptrVertexWriter64     void* ptr() const { return fPtr; }
65 
makeOffsetVertexWriter66     VertexWriter makeOffset(ptrdiff_t offsetInBytes) const {
67         return {SkTAddOffset<void>(fPtr, offsetInBytes)};
68     }
69 
70     template <typename T>
71     struct Conditional {
72         bool fCondition;
73         T fValue;
74     };
75 
76     template <typename T>
IfVertexWriter77     static Conditional<T> If(bool condition, const T& value) {
78         return {condition, value};
79     }
80 
81     template <typename T>
82     struct Skip {};
83 
84     template <typename T>
writeArrayVertexWriter85     void writeArray(const T* array, int count) {
86         static_assert(std::is_pod<T>::value, "");
87         memcpy(fPtr, array, count * sizeof(T));
88         fPtr = SkTAddOffset<void>(fPtr, count * sizeof(T));
89     }
90 
91     template <typename T>
fillVertexWriter92     void fill(const T& val, int repeatCount) {
93         for (int i = 0; i < repeatCount; ++i) {
94             *this << val;
95         }
96     }
97 
98     /**
99      * Specialized utilities for writing a four-vertices, with some data being replicated at each
100      * vertex, and other data being the appropriate 2-components from an SkRect to construct a
101      * triangle strip.
102      *
103      * - Four sets of data will be written
104      *
105      * - For any arguments where is_quad<Type>::value is true, a unique point will be written at
106      *   each vertex. To make a custom type be emitted as a quad, declare:
107      *
108      *       template<> struct VertexWriter::is_quad<MyQuadClass> : std::true_type {};
109      *
110      *   and define:
111      *
112      *       MyQuadClass::writeVertex(int cornerIdx, VertexWriter&) const { ... }
113      *
114      * - For any arguments where is_quad<Type>::value is false, its value will be replicated at each
115      *   vertex.
116      */
117     template <typename T>
118     struct is_quad : std::false_type {};
119 
120     template <typename T>
121     struct TriStrip {
writeVertexVertexWriter::TriStrip122         void writeVertex(int cornerIdx, VertexWriter& w) const {
123             switch (cornerIdx) {
124                 case 0: w << l << t; return;
125                 case 1: w << l << b; return;
126                 case 2: w << r << t; return;
127                 case 3: w << r << b; return;
128             }
129             SkUNREACHABLE;
130         }
131         T l, t, r, b;
132     };
133 
TriStripFromRectVertexWriter134     static TriStrip<float> TriStripFromRect(const SkRect& r) {
135         return { r.fLeft, r.fTop, r.fRight, r.fBottom };
136     }
137 
TriStripFromUVsVertexWriter138     static TriStrip<uint16_t> TriStripFromUVs(const std::array<uint16_t, 4>& rect) {
139         return { rect[0], rect[1], rect[2], rect[3] };
140     }
141 
142     template <typename T>
143     struct TriFan {
writeVertexVertexWriter::TriFan144         void writeVertex(int cornerIdx, VertexWriter& w) const {
145             switch (cornerIdx) {
146                 case 0: w << l << t; return;
147                 case 1: w << l << b; return;
148                 case 2: w << r << b; return;
149                 case 3: w << r << t; return;
150             }
151             SkUNREACHABLE;
152         }
153         T l, t, r, b;
154     };
155 
TriFanFromRectVertexWriter156     static TriFan<float> TriFanFromRect(const SkRect& r) {
157         return { r.fLeft, r.fTop, r.fRight, r.fBottom };
158     }
159 
160     template <typename... Args>
writeQuadVertexWriter161     void writeQuad(const Args&... remainder) {
162         this->writeQuadVertex<0>(remainder...);
163         this->writeQuadVertex<1>(remainder...);
164         this->writeQuadVertex<2>(remainder...);
165         this->writeQuadVertex<3>(remainder...);
166     }
167 
168 private:
169     template <int kCornerIdx, typename T, typename... Args>
writeQuadVertexVertexWriter170     std::enable_if_t<!is_quad<T>::value, void> writeQuadVertex(const T& val,
171                                                                const Args&... remainder) {
172         *this << val;  // Non-quads duplicate their value.
173         this->writeQuadVertex<kCornerIdx>(remainder...);
174     }
175 
176     template <int kCornerIdx, typename Q, typename... Args>
writeQuadVertexVertexWriter177     std::enable_if_t<is_quad<Q>::value, void> writeQuadVertex(const Q& quad,
178                                                               const Args&... remainder) {
179         quad.writeVertex(kCornerIdx, *this);  // Quads emit a different corner each time.
180         this->writeQuadVertex<kCornerIdx>(remainder...);
181     }
182 
183     template <int kCornerIdx>
writeQuadVertexVertexWriter184     void writeQuadVertex() {}
185 
186     template <typename T> friend VertexWriter& operator<<(VertexWriter& w, const T& val);
187 };
188 
189 template <typename T>
190 inline VertexWriter& operator<<(VertexWriter& w, const T& val) {
191     static_assert(std::is_pod<T>::value, "");
192     memcpy(w.fPtr, &val, sizeof(T));
193     w = w.makeOffset(sizeof(T));
194     return w;
195 }
196 
197 template <typename T>
198 inline VertexWriter& operator<<(VertexWriter& w, const VertexWriter::Conditional<T>& val) {
199     static_assert(std::is_pod<T>::value, "");
200     if (val.fCondition) {
201         w << val.fValue;
202     }
203     return w;
204 }
205 
206 template <typename T>
207 inline VertexWriter& operator<<(VertexWriter& w, const VertexWriter::Skip<T>& val) {
208     w = w.makeOffset(sizeof(T));
209     return w;
210 }
211 
212 template <>
213 SK_MAYBE_UNUSED inline VertexWriter& operator<<(VertexWriter& w, const Sk4f& vector) {
214     vector.store(w.fPtr);
215     w = w.makeOffset(sizeof(vector));
216     return w;
217 }
218 
219 template <typename T>
220 struct VertexWriter::is_quad<VertexWriter::TriStrip<T>> : std::true_type {};
221 
222 template <typename T>
223 struct VertexWriter::is_quad<VertexWriter::TriFan<T>> : std::true_type {};
224 
225 ///////////////////////////////////////////////////////////////////////////////////////////////////
226 
227 struct IndexWriter : public BufferWriter {
228     IndexWriter() = default;
229     IndexWriter(void* ptr) : BufferWriter(ptr) {}
230     IndexWriter(const IndexWriter&) = delete;
231     IndexWriter(IndexWriter&& that) { *this = std::move(that); }
232 
233     IndexWriter& operator=(const IndexWriter&) = delete;
234     IndexWriter& operator=(IndexWriter&& that) {
235         BufferWriter::operator=(std::move(that));
236         return *this;
237     }
238 
239     IndexWriter makeAdvance(int numIndices) const {
240         return {SkTAddOffset<void>(fPtr, numIndices * sizeof(uint16_t))};
241     }
242 
243     void writeArray(const uint16_t* array, int count) {
244         memcpy(fPtr, array, count * sizeof(uint16_t));
245         fPtr = SkTAddOffset<void>(fPtr, count * sizeof(uint16_t));
246     }
247 
248     friend IndexWriter& operator<<(IndexWriter& w, uint16_t val);
249 };
250 
251 inline IndexWriter& operator<<(IndexWriter& w, uint16_t val) {
252     memcpy(w.fPtr, &val, sizeof(uint16_t));
253     w = w.makeAdvance(1);
254     return w;
255 }
256 
257 ///////////////////////////////////////////////////////////////////////////////////////////////////
258 
259 struct UniformWriter : public BufferWriter {
260     UniformWriter() = default;
261     UniformWriter(void* ptr) : BufferWriter(ptr) {}
262     UniformWriter(const UniformWriter&) = delete;
263     UniformWriter(UniformWriter&& that) { *this = std::move(that); }
264 
265     UniformWriter& operator=(const UniformWriter&) = delete;
266     UniformWriter& operator=(UniformWriter&& that) {
267         BufferWriter::operator=(std::move(that));
268         return *this;
269     }
270 
271     void write(const void* src, size_t bytes) {
272         memcpy(fPtr, src, bytes);
273         fPtr = SkTAddOffset<void>(fPtr, bytes);
274     }
275 };
276 
277 }  // namespace skgpu
278 
279 #endif // BufferWriter_DEFINED
280