Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
BufferWriter.h
Go to the documentation of this file.
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 skgpu_BufferWriter_DEFINED
9#define skgpu_BufferWriter_DEFINED
10
12#include "include/core/SkRect.h"
19#include "src/base/SkVx.h"
21
22#include <array>
23#include <cstddef>
24#include <cstdint>
25#include <cstring>
26#include <type_traits>
27#include <utility>
28
29namespace skgpu {
30
32public:
33 // Marks a read-only position in the underlying buffer
34 struct Mark {
35 public:
36 Mark() : Mark(nullptr) {}
37 Mark(void* ptr, size_t offset = 0)
38 : fMark(reinterpret_cast<uintptr_t>(ptr) + offset) {
39 SkASSERT(ptr || offset == 0);
40 }
41
42 bool operator< (const Mark& o) const { return fMark < o.fMark; }
43 bool operator<=(const Mark& o) const { return fMark <= o.fMark; }
44 bool operator==(const Mark& o) const { return fMark == o.fMark; }
45 bool operator!=(const Mark& o) const { return fMark != o.fMark; }
46 bool operator>=(const Mark& o) const { return fMark >= o.fMark; }
47 bool operator> (const Mark& o) const { return fMark > o.fMark; }
48
49 ptrdiff_t operator-(const Mark& o) const { return fMark - o.fMark; }
50
51 explicit operator bool() const { return *this != Mark(); }
52 private:
53 uintptr_t fMark;
54 };
55
56 explicit operator bool() const { return fPtr != nullptr; }
57
58 Mark mark(size_t offset=0) const {
59 this->validate(offset);
60 return Mark(fPtr, offset);
61 }
62
63protected:
64 BufferWriter() = default;
65 BufferWriter(void* ptr, size_t size) : fPtr(ptr) {
66 SkDEBUGCODE(fEnd = Mark(ptr, ptr ? size : 0);)
67 }
68 BufferWriter(void* ptr, Mark end = {}) : fPtr(ptr) {
69 SkDEBUGCODE(fEnd = end;)
70 }
71
74 fPtr = that.fPtr;
75 that.fPtr = nullptr;
76 SkDEBUGCODE(fEnd = that.fEnd;)
77 SkDEBUGCODE(that.fEnd = Mark();)
78 return *this;
79 }
80
81 // makeOffset effectively splits the current writer from {fPtr, fEnd} into {fPtr, p} and
82 // a new writer {p, fEnd}. The same data range is accessible, but each byte can only be
83 // set by a single writer. Automatically validates that there is enough bytes remaining in this
84 // writer to do such a split.
85 //
86 // This splitting and validation means that providers of BufferWriters to callers can easily
87 // and correctly track everything in a single BufferWriter field and use
88 // return std::exchange(fCurrWriter, fCurrWriter.makeOffset(requestedBytes));
89 // This exposes the current writer position to the caller and sets the provider's new current
90 // position to be just after the requested bytes.
91 //
92 // Templated so that it can create subclasses directly.
93 template<typename W>
94 W makeOffset(size_t offsetInBytes) const {
95 this->validate(offsetInBytes);
96 void* p = SkTAddOffset<void>(fPtr, offsetInBytes);
97 Mark end{SkDEBUGCODE(fEnd)};
98 SkDEBUGCODE(fEnd = Mark(p);)
99 return W{p, end};
100 }
101
102 void validate(size_t bytesToWrite) const {
103 // If the buffer writer had an end marked, make sure we're not crossing it.
104 // Ideally, all creators of BufferWriters mark the end, but a lot of legacy code is not set
105 // up to easily do this.
106 SkASSERT(fPtr || bytesToWrite == 0);
107 SkASSERT(!fEnd || Mark(fPtr, bytesToWrite) <= fEnd);
108 }
109
110protected:
111 void* fPtr = nullptr;
112 SkDEBUGCODE(mutable Mark fEnd = {};)
113};
114
115/**
116 * Helper for writing vertex data to a buffer. Usage:
117 * VertexWriter vertices{target->makeVertexSpace(...)};
118 * vertices << A0 << B0 << C0 << ...;
119 * vertices << A1 << B1 << C1 << ...;
120 *
121 * Each value must be POD (plain old data), or have a specialization of the "<<" operator.
122 */
123struct VertexWriter : public BufferWriter {
124 inline constexpr static uint32_t kIEEE_32_infinity = 0x7f800000;
125
126 VertexWriter() = default;
127 // DEPRECATED: Prefer specifying the size of the buffer being written to as well
128 explicit VertexWriter(void* ptr) : BufferWriter(ptr, Mark()) {}
129
130 VertexWriter(void* ptr, size_t size) : BufferWriter(ptr, size) {}
131 VertexWriter(void* ptr, Mark end) : BufferWriter(ptr, end) {}
132
133 VertexWriter(const VertexWriter&) = delete;
134 VertexWriter(VertexWriter&& that) { *this = std::move(that); }
135
138 BufferWriter::operator=(std::move(that));
139 return *this;
140 }
141
142 VertexWriter makeOffset(size_t offsetInBytes) const {
143 return this->BufferWriter::makeOffset<VertexWriter>(offsetInBytes);
144 }
145
146 template <typename T>
147 struct Conditional {
150 };
151
152 template <typename T>
153 static Conditional<T> If(bool condition, const T& value) {
154 return {condition, value};
155 }
156
157 template <typename T>
158 struct Skip {};
159
160 template<typename T>
161 struct ArrayDesc {
162 const T* fArray;
164 };
165
166 template <typename T>
167 static ArrayDesc<T> Array(const T* array, int count) {
168 return {array, count};
169 }
170
171 template<int kCount, typename T>
172 struct RepeatDesc {
173 const T& fVal;
174 };
175
176 template <int kCount, typename T>
177 static RepeatDesc<kCount, T> Repeat(const T& val) {
178 return {val};
179 }
180
181 /**
182 * Specialized utilities for writing a four-vertices, with some data being replicated at each
183 * vertex, and other data being the appropriate 2-components from an SkRect to construct a
184 * triangle strip.
185 *
186 * - Four sets of data will be written
187 *
188 * - For any arguments where is_quad<Type>::value is true, a unique point will be written at
189 * each vertex. To make a custom type be emitted as a quad, declare:
190 *
191 * template<> struct VertexWriter::is_quad<MyQuadClass> : std::true_type {};
192 *
193 * and define:
194 *
195 * MyQuadClass::writeVertex(int cornerIdx, VertexWriter&) const { ... }
196 *
197 * - For any arguments where is_quad<Type>::value is false, its value will be replicated at each
198 * vertex.
199 */
200 template <typename T>
201 struct is_quad : std::false_type {};
202
203 template <typename T>
204 struct TriStrip {
205 void writeVertex(int cornerIdx, VertexWriter& w) const {
206 switch (cornerIdx) {
207 case 0: w << l << t; return;
208 case 1: w << l << b; return;
209 case 2: w << r << t; return;
210 case 3: w << r << b; return;
211 }
213 }
214 T l, t, r, b;
215 };
216
218 return { r.fLeft, r.fTop, r.fRight, r.fBottom };
219 }
220
221 static TriStrip<uint16_t> TriStripFromUVs(const std::array<uint16_t, 4>& rect) {
222 return { rect[0], rect[1], rect[2], rect[3] };
223 }
224
225 template <typename T>
226 struct TriFan {
227 void writeVertex(int cornerIdx, VertexWriter& w) const {
228 switch (cornerIdx) {
229 case 0: w << l << t; return;
230 case 1: w << l << b; return;
231 case 2: w << r << b; return;
232 case 3: w << r << t; return;
233 }
235 }
236 T l, t, r, b;
237 };
238
240 return { r.fLeft, r.fTop, r.fRight, r.fBottom };
241 }
242
243 template <typename... Args>
244 void writeQuad(const Args&... remainder) {
245 this->writeQuadVertex<0>(remainder...);
246 this->writeQuadVertex<1>(remainder...);
247 this->writeQuadVertex<2>(remainder...);
248 this->writeQuadVertex<3>(remainder...);
249 }
250
251private:
252 template <int kCornerIdx, typename T, typename... Args>
253 std::enable_if_t<!is_quad<T>::value, void> writeQuadVertex(const T& val,
254 const Args&... remainder) {
255 *this << val; // Non-quads duplicate their value.
256 this->writeQuadVertex<kCornerIdx>(remainder...);
257 }
258
259 template <int kCornerIdx, typename Q, typename... Args>
260 std::enable_if_t<is_quad<Q>::value, void> writeQuadVertex(const Q& quad,
261 const Args&... remainder) {
262 quad.writeVertex(kCornerIdx, *this); // Quads emit a different corner each time.
263 this->writeQuadVertex<kCornerIdx>(remainder...);
264 }
265
266 template <int kCornerIdx>
267 void writeQuadVertex() {}
268
269 template <typename T>
270 friend VertexWriter& operator<<(VertexWriter&, const T&);
271
272 template <typename T>
273 friend VertexWriter& operator<<(VertexWriter&, const ArrayDesc<T>&);
274};
275
276template <typename T>
277inline VertexWriter& operator<<(VertexWriter& w, const T& val) {
278 static_assert(std::is_trivially_copyable<T>::value, "");
279 w.validate(sizeof(T));
280 memcpy(w.fPtr, &val, sizeof(T));
281 w = w.makeOffset(sizeof(T));
282 return w;
283}
284
285template <typename T>
287 static_assert(std::is_trivially_copyable<T>::value, "");
288 if (val.fCondition) {
289 w << val.fValue;
290 }
291 return w;
292}
293
294template <typename T>
296 w = w.makeOffset(sizeof(T));
297 return w;
298}
299
300template <typename T>
302 static_assert(std::is_trivially_copyable<T>::value, "");
303 w.validate(array.fCount * sizeof(T));
304 memcpy(w.fPtr, array.fArray, array.fCount * sizeof(T));
305 w = w.makeOffset(sizeof(T) * array.fCount);
306 return w;
307}
308
309template <int kCount, typename T>
311 for (int i = 0; i < kCount; ++i) {
312 w << repeat.fVal;
313 }
314 return w;
315}
316
317template <>
318[[maybe_unused]] inline VertexWriter& operator<<(VertexWriter& w, const skvx::float4& vector) {
319 w.validate(sizeof(vector));
320 vector.store(w.fPtr);
321 w = w.makeOffset(sizeof(vector));
322 return w;
323}
324
325// Allow r-value/temporary writers to be appended to
326template <typename T>
327inline VertexWriter& operator<<(VertexWriter&& w, const T& val) { return w << val; }
328
329template <typename T>
330struct VertexWriter::is_quad<VertexWriter::TriStrip<T>> : std::true_type {};
331
332template <typename T>
333struct VertexWriter::is_quad<VertexWriter::TriFan<T>> : std::true_type {};
334
335/**
336 * VertexColor is a helper for writing colors to a vertex buffer. It outputs either four bytes or
337 * or four float32 channels, depending on the wideColor parameter. Note that the GP needs to have
338 * been constructed with the correct attribute type for colors, to match the usage here.
339 */
341public:
342 VertexColor() = default;
343
344 explicit VertexColor(const SkPMColor4f& color, bool wideColor) {
345 this->set(color, wideColor);
346 }
347
348 void set(const SkPMColor4f& color, bool wideColor) {
349 if (wideColor) {
350 memcpy(fColor, color.vec(), sizeof(fColor));
351 } else {
352 fColor[0] = color.toBytes_RGBA();
353 }
354 fWideColor = wideColor;
355 }
356
357 size_t size() const { return fWideColor ? 16 : 4; }
358
359private:
360 template <typename T>
361 friend VertexWriter& operator<<(VertexWriter&, const T&);
362
363 uint32_t fColor[4];
364 bool fWideColor;
365};
366
367template <>
368[[maybe_unused]] inline VertexWriter& operator<<(VertexWriter& w, const VertexColor& color) {
369 w << color.fColor[0];
370 if (color.fWideColor) {
371 w << color.fColor[1]
372 << color.fColor[2]
373 << color.fColor[3];
374 }
375 return w;
376}
377
378///////////////////////////////////////////////////////////////////////////////////////////////////
379
380struct IndexWriter : public BufferWriter {
381 IndexWriter() = default;
382
383 IndexWriter(void* ptr, size_t size) : BufferWriter(ptr, size) {}
384 IndexWriter(void* ptr, Mark end) : BufferWriter(ptr, end) {}
385
386 IndexWriter(const IndexWriter&) = delete;
387 IndexWriter(IndexWriter&& that) { *this = std::move(that); }
388
391 BufferWriter::operator=(std::move(that));
392 return *this;
393 }
394
395 IndexWriter makeOffset(int numIndices) const {
396 return this->BufferWriter::makeOffset<IndexWriter>(numIndices * sizeof(uint16_t));
397 }
398
399 void writeArray(const uint16_t* array, int count) {
400 size_t arraySize = count * sizeof(uint16_t);
401 this->validate(arraySize);
402 memcpy(fPtr, array, arraySize);
403 fPtr = SkTAddOffset<void>(fPtr, arraySize);
404
405 }
406
407 friend IndexWriter& operator<<(IndexWriter& w, uint16_t val);
408};
409
410inline IndexWriter& operator<<(IndexWriter& w, uint16_t val) {
411 w.validate(sizeof(uint16_t));
412 memcpy(w.fPtr, &val, sizeof(uint16_t));
413 w = w.makeOffset(1);
414 return w;
415}
416
417inline IndexWriter& operator<<(IndexWriter& w, int val) { return (w << SkTo<uint16_t>(val)); }
418
419template<typename T>
420inline IndexWriter& operator<<(IndexWriter&& w, const T& val) { return w << val; }
421
422///////////////////////////////////////////////////////////////////////////////////////////////////
423
425 UniformWriter() = default;
426
427 UniformWriter(void* ptr, size_t size) : BufferWriter(ptr, size) {}
428 UniformWriter(void* ptr, Mark end) : BufferWriter(ptr, end) {}
429
430 UniformWriter(const UniformWriter&) = delete;
431 UniformWriter(UniformWriter&& that) { *this = std::move(that); }
432
435 BufferWriter::operator=(std::move(that));
436 return *this;
437 }
438
439 void write(const void* src, size_t bytes) {
440 this->validate(bytes);
441 memcpy(fPtr, src, bytes);
442 fPtr = SkTAddOffset<void>(fPtr, bytes);
443 }
444 void skipBytes(size_t bytes) {
445 this->validate(bytes);
446 fPtr = SkTAddOffset<void>(fPtr, bytes);
447 }
448};
449
450///////////////////////////////////////////////////////////////////////////////////////////////////
451
454
455 TextureUploadWriter(void* ptr, size_t size) : BufferWriter(ptr, size) {}
456
458 TextureUploadWriter(TextureUploadWriter&& that) { *this = std::move(that); }
459
462 BufferWriter::operator=(std::move(that));
463 return *this;
464 }
465
466 // Writes a block of image data to the upload buffer, starting at `offset`. The source image is
467 // `srcRowBytes` wide, and the written block is `dstRowBytes` wide and `rowCount` bytes tall.
468 void write(size_t offset, const void* src, size_t srcRowBytes, size_t dstRowBytes,
469 size_t trimRowBytes, int rowCount) {
470 this->validate(offset + dstRowBytes * rowCount);
471 void* dst = SkTAddOffset<void>(fPtr, offset);
472 SkRectMemcpy(dst, dstRowBytes, src, srcRowBytes, trimRowBytes, rowCount);
473 }
474
476 const SkImageInfo& srcInfo, const void* src, size_t srcRowBytes,
477 const SkImageInfo& dstInfo, size_t dstRowBytes) {
478 SkASSERT(srcInfo.width() == dstInfo.width() && srcInfo.height() == dstInfo.height());
479 this->validate(offset + dstRowBytes * dstInfo.height());
480 void* dst = SkTAddOffset<void>(fPtr, offset);
481 SkAssertResult(SkConvertPixels(dstInfo, dst, dstRowBytes, srcInfo, src, srcRowBytes));
482 }
483
484 // Writes a block of image data to the upload buffer. It converts src data of RGB_888x
485 // colorType into a 3 channel RGB_888 format.
486 void writeRGBFromRGBx(size_t offset, const void* src, size_t srcRowBytes, size_t dstRowBytes,
487 int rowPixels, int rowCount) {
488 this->validate(offset + dstRowBytes * rowCount);
489 void* dst = SkTAddOffset<void>(fPtr, offset);
490 auto* sRow = reinterpret_cast<const char*>(src);
491 auto* dRow = reinterpret_cast<char*>(dst);
492
493 for (int y = 0; y < rowCount; ++y) {
494 for (int x = 0; x < rowPixels; ++x) {
495 memcpy(dRow + 3*x, sRow+4*x, 3);
496 }
497 sRow += srcRowBytes;
498 dRow += dstRowBytes;
499 }
500 }
501};
502
503} // namespace skgpu
504
505#endif // skgpu_BufferWriter_DEFINED
int count
SkColor4f color
#define SkAssertResult(cond)
Definition SkAssert.h:123
#define SkUNREACHABLE
Definition SkAssert.h:135
#define SkASSERT(cond)
Definition SkAssert.h:116
static unsigned repeat(SkFixed fx, int max)
bool SkConvertPixels(const SkImageInfo &dstInfo, void *dstPixels, size_t dstRB, const SkImageInfo &srcInfo, const void *srcPixels, size_t srcRB)
#define SkDEBUGCODE(...)
Definition SkDebug.h:23
static void SkRectMemcpy(void *dst, size_t dstRB, const void *src, size_t srcRB, size_t trimRowBytes, int rowCount)
#define W
Definition aaa.cpp:17
VertexColor(const SkPMColor4f &color, bool wideColor)
friend VertexWriter & operator<<(VertexWriter &, const T &)
void set(const SkPMColor4f &color, bool wideColor)
size_t size() const
VertexColor()=default
glong glong end
uint8_t value
double y
double x
VertexWriter & operator<<(VertexWriter &w, const T &val)
SkScalar w
#define T
Point offset
int width() const
int height() const
SkScalar fBottom
larger y-axis bounds
Definition extension.cpp:17
SkScalar fLeft
smaller x-axis bounds
Definition extension.cpp:14
SkScalar fRight
larger x-axis bounds
Definition extension.cpp:16
SkScalar fTop
smaller y-axis bounds
Definition extension.cpp:15
bool operator==(const Mark &o) const
ptrdiff_t operator-(const Mark &o) const
Mark(void *ptr, size_t offset=0)
bool operator>=(const Mark &o) const
bool operator<=(const Mark &o) const
bool operator!=(const Mark &o) const
bool operator<(const Mark &o) const
bool operator>(const Mark &o) const
BufferWriter & operator=(const BufferWriter &)=delete
BufferWriter(void *ptr, Mark end={})
BufferWriter & operator=(BufferWriter &&that)
BufferWriter()=default
W makeOffset(size_t offsetInBytes) const
Mark mark(size_t offset=0) const
BufferWriter(void *ptr, size_t size)
void validate(size_t bytesToWrite) const
IndexWriter()=default
IndexWriter(IndexWriter &&that)
IndexWriter(const IndexWriter &)=delete
IndexWriter(void *ptr, Mark end)
friend IndexWriter & operator<<(IndexWriter &w, uint16_t val)
IndexWriter(void *ptr, size_t size)
IndexWriter makeOffset(int numIndices) const
void writeArray(const uint16_t *array, int count)
IndexWriter & operator=(const IndexWriter &)=delete
IndexWriter & operator=(IndexWriter &&that)
TextureUploadWriter & operator=(TextureUploadWriter &&that)
TextureUploadWriter & operator=(const TextureUploadWriter &)=delete
void convertAndWrite(size_t offset, const SkImageInfo &srcInfo, const void *src, size_t srcRowBytes, const SkImageInfo &dstInfo, size_t dstRowBytes)
TextureUploadWriter(const TextureUploadWriter &)=delete
void writeRGBFromRGBx(size_t offset, const void *src, size_t srcRowBytes, size_t dstRowBytes, int rowPixels, int rowCount)
void write(size_t offset, const void *src, size_t srcRowBytes, size_t dstRowBytes, size_t trimRowBytes, int rowCount)
TextureUploadWriter(void *ptr, size_t size)
TextureUploadWriter(TextureUploadWriter &&that)
void skipBytes(size_t bytes)
UniformWriter(void *ptr, size_t size)
UniformWriter(void *ptr, Mark end)
UniformWriter(UniformWriter &&that)
void write(const void *src, size_t bytes)
UniformWriter & operator=(const UniformWriter &)=delete
UniformWriter & operator=(UniformWriter &&that)
UniformWriter(const UniformWriter &)=delete
void writeVertex(int cornerIdx, VertexWriter &w) const
void writeVertex(int cornerIdx, VertexWriter &w) const
VertexWriter(const VertexWriter &)=delete
static RepeatDesc< kCount, T > Repeat(const T &val)
static ArrayDesc< T > Array(const T *array, int count)
static TriStrip< uint16_t > TriStripFromUVs(const std::array< uint16_t, 4 > &rect)
friend VertexWriter & operator<<(VertexWriter &, const T &)
VertexWriter & operator=(VertexWriter &&that)
static TriFan< float > TriFanFromRect(const SkRect &r)
VertexWriter()=default
VertexWriter(void *ptr, Mark end)
void writeQuad(const Args &... remainder)
static Conditional< T > If(bool condition, const T &value)
static TriStrip< float > TriStripFromRect(const SkRect &r)
static constexpr uint32_t kIEEE_32_infinity
VertexWriter & operator=(const VertexWriter &)=delete
VertexWriter(void *ptr)
VertexWriter(void *ptr, size_t size)
VertexWriter makeOffset(size_t offsetInBytes) const
VertexWriter(VertexWriter &&that)
SKVX_ALWAYS_INLINE void store(void *ptr) const
Definition SkVx.h:112