blob: a4c13a32168e460374469285d29fe8dbbf6f4830 [file] [log] [blame]
Brian Osmanf9aabff2018-11-13 16:11:38 -05001/*
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 GrVertexWriter_DEFINED
9#define GrVertexWriter_DEFINED
10
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "include/private/SkTemplates.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040012#include "src/gpu/GrColor.h"
Michael Ludwigfd4f4df2019-05-29 09:51:09 -040013#include "src/gpu/geometry/GrQuad.h"
Brian Osmanf9aabff2018-11-13 16:11:38 -050014#include <type_traits>
15
16/**
17 * Helper for writing vertex data to a buffer. Usage:
18 * GrVertexWriter vertices{target->makeVertexSpace(...)};
19 * vertices.write(A0, B0, C0, ...);
20 * vertices.write(A1, B1, C1, ...);
21 *
22 * Supports any number of arguments. Each argument must be POD (plain old data), or an array
23 * thereof.
24 */
25struct GrVertexWriter {
Chris Dalton3febc612021-07-14 13:47:07 -060026 constexpr static uint32_t kIEEE_32_infinity = 0x7f800000;
27
Brian Osman4486d982018-11-15 15:56:04 -050028 void* fPtr;
29
Chris Daltona43d5832021-02-07 21:10:32 -070030 GrVertexWriter() = default;
31 GrVertexWriter(void* ptr) : fPtr(ptr) {}
32 GrVertexWriter(const GrVertexWriter&) = delete;
33 GrVertexWriter(GrVertexWriter&& that) { *this = std::move(that); }
34
35 GrVertexWriter& operator=(const GrVertexWriter&) = delete;
36 GrVertexWriter& operator=(GrVertexWriter&& that) {
37 fPtr = that.fPtr;
38 that.fPtr = nullptr;
39 return *this;
40 }
41
Chris Dalton8ed7a8d2021-03-31 10:40:29 -060042 bool operator==(const GrVertexWriter& that) const { return fPtr == that.fPtr; }
43 operator bool() const { return fPtr != nullptr; }
Chris Daltona43d5832021-02-07 21:10:32 -070044
Chris Dalton8447f132021-05-21 15:54:23 -060045 GrVertexWriter makeOffset(ptrdiff_t offsetInBytes) const {
Chris Daltona43d5832021-02-07 21:10:32 -070046 return {SkTAddOffset<void>(fPtr, offsetInBytes)};
47 }
48
Brian Osmancfec9d52018-11-20 11:39:15 -050049 template <typename T>
50 class Conditional {
51 public:
52 explicit Conditional(bool condition, const T& value)
53 : fCondition(condition), fValue(value) {}
54 private:
55 friend struct GrVertexWriter;
56
57 bool fCondition;
58 T fValue;
59 };
60
61 template <typename T>
62 static Conditional<T> If(bool condition, const T& value) {
63 return Conditional<T>(condition, value);
64 }
65
Brian Osmand2fa2eb2018-12-26 16:48:40 -050066 template <typename T>
67 struct Skip {};
68
Brian Osmanf9aabff2018-11-13 16:11:38 -050069 template <typename T, typename... Args>
70 void write(const T& val, const Args&... remainder) {
71 static_assert(std::is_pod<T>::value, "");
Brian Osmanf9aabff2018-11-13 16:11:38 -050072 memcpy(fPtr, &val, sizeof(T));
73 fPtr = SkTAddOffset<void>(fPtr, sizeof(T));
74 this->write(remainder...);
75 }
76
77 template <typename T, size_t N, typename... Args>
78 void write(const T(&val)[N], const Args&... remainder) {
79 static_assert(std::is_pod<T>::value, "");
Brian Osmanf9aabff2018-11-13 16:11:38 -050080 memcpy(fPtr, val, N * sizeof(T));
81 fPtr = SkTAddOffset<void>(fPtr, N * sizeof(T));
82 this->write(remainder...);
83 }
84
Brian Osman5c8a6b32018-11-19 11:56:57 -050085 template <typename... Args>
86 void write(const GrVertexColor& color, const Args&... remainder) {
87 this->write(color.fColor[0]);
88 if (color.fWideColor) {
89 this->write(color.fColor[1]);
Brian Osman2715bf52019-12-06 14:38:47 -050090 this->write(color.fColor[2]);
91 this->write(color.fColor[3]);
Brian Osman5c8a6b32018-11-19 11:56:57 -050092 }
93 this->write(remainder...);
94 }
95
Brian Osmancfec9d52018-11-20 11:39:15 -050096 template <typename T, typename... Args>
97 void write(const Conditional<T>& val, const Args&... remainder) {
98 if (val.fCondition) {
99 this->write(val.fValue);
100 }
101 this->write(remainder...);
102 }
103
Brian Osmand2fa2eb2018-12-26 16:48:40 -0500104 template <typename T, typename... Args>
105 void write(const Skip<T>& val, const Args&... remainder) {
106 fPtr = SkTAddOffset<void>(fPtr, sizeof(T));
107 this->write(remainder...);
108 }
109
Michael Ludwigf995c052018-11-26 15:24:29 -0500110 template <typename... Args>
111 void write(const Sk4f& vector, const Args&... remainder) {
112 float buffer[4];
113 vector.store(buffer);
114 this->write<float, 4>(buffer);
115 this->write(remainder...);
116 }
117
Chris Daltona43d5832021-02-07 21:10:32 -0700118 template <typename T>
119 void writeArray(const T* array, int count) {
120 static_assert(std::is_pod<T>::value, "");
Chris Daltona43d5832021-02-07 21:10:32 -0700121 memcpy(fPtr, array, count * sizeof(T));
122 fPtr = SkTAddOffset<void>(fPtr, count * sizeof(T));
123 }
124
125 template <typename T>
126 void fill(const T& val, int repeatCount) {
127 for (int i = 0; i < repeatCount; ++i) {
128 this->write(val);
129 }
130 }
131
Brian Osmanffd11f4a2020-03-30 09:57:53 -0400132 void writeRaw(const void* data, size_t size) {
133 memcpy(fPtr, data, size);
134 fPtr = SkTAddOffset<void>(fPtr, size);
135 }
136
Brian Osmanf9aabff2018-11-13 16:11:38 -0500137 void write() {}
138
Brian Osman4486d982018-11-15 15:56:04 -0500139 /**
140 * Specialized utility for writing a four-vertices, with some data being replicated at each
141 * vertex, and other data being the appropriate 2-components from an SkRect to construct a
142 * triangle strip.
143 *
144 * writeQuad(A, B, C, ...) is similar to write(A, B, C, ...), except that:
145 *
146 * - Four sets of data will be written
147 * - For any arguments of type TriStrip, a unique SkPoint will be written at each vertex,
148 * in this order: left-top, left-bottom, right-top, right-bottom.
149 */
Brian Osman0dd43022018-11-16 15:53:26 -0500150 template <typename T>
151 struct TriStrip { T l, t, r, b; };
152
153 static TriStrip<float> TriStripFromRect(const SkRect& r) {
154 return { r.fLeft, r.fTop, r.fRight, r.fBottom };
155 }
Brian Osman4486d982018-11-15 15:56:04 -0500156
Robert Phillips6d3bc292020-04-06 10:29:28 -0400157 static TriStrip<uint16_t> TriStripFromUVs(const std::array<uint16_t, 4>& rect) {
158 return { rect[0], rect[1], rect[2], rect[3] };
159 }
160
Brian Osmancfec9d52018-11-20 11:39:15 -0500161 template <typename T>
162 struct TriFan { T l, t, r, b; };
163
164 static TriFan<float> TriFanFromRect(const SkRect& r) {
165 return { r.fLeft, r.fTop, r.fRight, r.fBottom };
166 }
167
Brian Osman4486d982018-11-15 15:56:04 -0500168 template <typename... Args>
169 void writeQuad(const Args&... remainder) {
170 this->writeQuadVert<0>(remainder...);
171 this->writeQuadVert<1>(remainder...);
172 this->writeQuadVert<2>(remainder...);
173 this->writeQuadVert<3>(remainder...);
174 }
175
176private:
177 template <int corner, typename T, typename... Args>
178 void writeQuadVert(const T& val, const Args&... remainder) {
179 this->writeQuadValue<corner>(val);
180 this->writeQuadVert<corner>(remainder...);
181 }
182
183 template <int corner>
184 void writeQuadVert() {}
185
186 template <int corner, typename T>
187 void writeQuadValue(const T& val) {
188 this->write(val);
189 }
190
Brian Osman0dd43022018-11-16 15:53:26 -0500191 template <int corner, typename T>
192 void writeQuadValue(const TriStrip<T>& r) {
Brian Osman4486d982018-11-15 15:56:04 -0500193 switch (corner) {
Brian Osman0dd43022018-11-16 15:53:26 -0500194 case 0: this->write(r.l, r.t); break;
195 case 1: this->write(r.l, r.b); break;
196 case 2: this->write(r.r, r.t); break;
197 case 3: this->write(r.r, r.b); break;
Brian Osman4486d982018-11-15 15:56:04 -0500198 }
199 }
Brian Osman0dd43022018-11-16 15:53:26 -0500200
Brian Osmancfec9d52018-11-20 11:39:15 -0500201 template <int corner, typename T>
202 void writeQuadValue(const TriFan<T>& r) {
203 switch (corner) {
204 case 0: this->write(r.l, r.t); break;
205 case 1: this->write(r.l, r.b); break;
206 case 2: this->write(r.r, r.b); break;
207 case 3: this->write(r.r, r.t); break;
208 }
209 }
210
Brian Osman0dd43022018-11-16 15:53:26 -0500211 template <int corner>
212 void writeQuadValue(const GrQuad& q) {
213 this->write(q.point(corner));
214 }
Brian Osmanf9aabff2018-11-13 16:11:38 -0500215};
216
217#endif