123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- /*
- * Copyright 2010 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
- #ifndef GrVertexWriter_DEFINED
- #define GrVertexWriter_DEFINED
- #include "include/private/SkTemplates.h"
- #include "src/gpu/GrColor.h"
- #include "src/gpu/geometry/GrQuad.h"
- #include <type_traits>
- /**
- * Helper for writing vertex data to a buffer. Usage:
- * GrVertexWriter vertices{target->makeVertexSpace(...)};
- * vertices.write(A0, B0, C0, ...);
- * vertices.write(A1, B1, C1, ...);
- *
- * Supports any number of arguments. Each argument must be POD (plain old data), or an array
- * thereof.
- */
- struct GrVertexWriter {
- void* fPtr;
- template <typename T>
- class Conditional {
- public:
- explicit Conditional(bool condition, const T& value)
- : fCondition(condition), fValue(value) {}
- private:
- friend struct GrVertexWriter;
- bool fCondition;
- T fValue;
- };
- template <typename T>
- static Conditional<T> If(bool condition, const T& value) {
- return Conditional<T>(condition, value);
- }
- template <typename T>
- struct Skip {};
- template <typename T, typename... Args>
- void write(const T& val, const Args&... remainder) {
- static_assert(std::is_pod<T>::value, "");
- // This assert is barely related to what we're trying to check - that our vertex data
- // matches our attribute layouts, where each attribute is aligned to four bytes. If this
- // becomes a problem, just remove it.
- static_assert(alignof(T) <= 4, "");
- memcpy(fPtr, &val, sizeof(T));
- fPtr = SkTAddOffset<void>(fPtr, sizeof(T));
- this->write(remainder...);
- }
- template <typename T, size_t N, typename... Args>
- void write(const T(&val)[N], const Args&... remainder) {
- static_assert(std::is_pod<T>::value, "");
- static_assert(alignof(T) <= 4, "");
- memcpy(fPtr, val, N * sizeof(T));
- fPtr = SkTAddOffset<void>(fPtr, N * sizeof(T));
- this->write(remainder...);
- }
- template <typename... Args>
- void write(const GrVertexColor& color, const Args&... remainder) {
- this->write(color.fColor[0]);
- if (color.fWideColor) {
- this->write(color.fColor[1]);
- }
- this->write(remainder...);
- }
- template <typename T, typename... Args>
- void write(const Conditional<T>& val, const Args&... remainder) {
- if (val.fCondition) {
- this->write(val.fValue);
- }
- this->write(remainder...);
- }
- template <typename T, typename... Args>
- void write(const Skip<T>& val, const Args&... remainder) {
- fPtr = SkTAddOffset<void>(fPtr, sizeof(T));
- this->write(remainder...);
- }
- template <typename... Args>
- void write(const Sk4f& vector, const Args&... remainder) {
- float buffer[4];
- vector.store(buffer);
- this->write<float, 4>(buffer);
- this->write(remainder...);
- }
- void write() {}
- /**
- * Specialized utility for writing a four-vertices, with some data being replicated at each
- * vertex, and other data being the appropriate 2-components from an SkRect to construct a
- * triangle strip.
- *
- * writeQuad(A, B, C, ...) is similar to write(A, B, C, ...), except that:
- *
- * - Four sets of data will be written
- * - For any arguments of type TriStrip, a unique SkPoint will be written at each vertex,
- * in this order: left-top, left-bottom, right-top, right-bottom.
- */
- template <typename T>
- struct TriStrip { T l, t, r, b; };
- static TriStrip<float> TriStripFromRect(const SkRect& r) {
- return { r.fLeft, r.fTop, r.fRight, r.fBottom };
- }
- template <typename T>
- struct TriFan { T l, t, r, b; };
- static TriFan<float> TriFanFromRect(const SkRect& r) {
- return { r.fLeft, r.fTop, r.fRight, r.fBottom };
- }
- template <typename... Args>
- void writeQuad(const Args&... remainder) {
- this->writeQuadVert<0>(remainder...);
- this->writeQuadVert<1>(remainder...);
- this->writeQuadVert<2>(remainder...);
- this->writeQuadVert<3>(remainder...);
- }
- private:
- template <int corner, typename T, typename... Args>
- void writeQuadVert(const T& val, const Args&... remainder) {
- this->writeQuadValue<corner>(val);
- this->writeQuadVert<corner>(remainder...);
- }
- template <int corner>
- void writeQuadVert() {}
- template <int corner, typename T>
- void writeQuadValue(const T& val) {
- this->write(val);
- }
- template <int corner, typename T>
- void writeQuadValue(const TriStrip<T>& r) {
- switch (corner) {
- case 0: this->write(r.l, r.t); break;
- case 1: this->write(r.l, r.b); break;
- case 2: this->write(r.r, r.t); break;
- case 3: this->write(r.r, r.b); break;
- }
- }
- template <int corner, typename T>
- void writeQuadValue(const TriFan<T>& r) {
- switch (corner) {
- case 0: this->write(r.l, r.t); break;
- case 1: this->write(r.l, r.b); break;
- case 2: this->write(r.r, r.b); break;
- case 3: this->write(r.r, r.t); break;
- }
- }
- template <int corner>
- void writeQuadValue(const GrQuad& q) {
- this->write(q.point(corner));
- }
- };
- #endif
|