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