GrVertexWriter.h 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  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. #ifndef GrVertexWriter_DEFINED
  8. #define GrVertexWriter_DEFINED
  9. #include "include/private/SkTemplates.h"
  10. #include "src/gpu/GrColor.h"
  11. #include "src/gpu/geometry/GrQuad.h"
  12. #include <type_traits>
  13. /**
  14. * Helper for writing vertex data to a buffer. Usage:
  15. * GrVertexWriter vertices{target->makeVertexSpace(...)};
  16. * vertices.write(A0, B0, C0, ...);
  17. * vertices.write(A1, B1, C1, ...);
  18. *
  19. * Supports any number of arguments. Each argument must be POD (plain old data), or an array
  20. * thereof.
  21. */
  22. struct GrVertexWriter {
  23. void* fPtr;
  24. template <typename T>
  25. class Conditional {
  26. public:
  27. explicit Conditional(bool condition, const T& value)
  28. : fCondition(condition), fValue(value) {}
  29. private:
  30. friend struct GrVertexWriter;
  31. bool fCondition;
  32. T fValue;
  33. };
  34. template <typename T>
  35. static Conditional<T> If(bool condition, const T& value) {
  36. return Conditional<T>(condition, value);
  37. }
  38. template <typename T>
  39. struct Skip {};
  40. template <typename T, typename... Args>
  41. void write(const T& val, const Args&... remainder) {
  42. static_assert(std::is_pod<T>::value, "");
  43. // This assert is barely related to what we're trying to check - that our vertex data
  44. // matches our attribute layouts, where each attribute is aligned to four bytes. If this
  45. // becomes a problem, just remove it.
  46. static_assert(alignof(T) <= 4, "");
  47. memcpy(fPtr, &val, sizeof(T));
  48. fPtr = SkTAddOffset<void>(fPtr, sizeof(T));
  49. this->write(remainder...);
  50. }
  51. template <typename T, size_t N, typename... Args>
  52. void write(const T(&val)[N], const Args&... remainder) {
  53. static_assert(std::is_pod<T>::value, "");
  54. static_assert(alignof(T) <= 4, "");
  55. memcpy(fPtr, val, N * sizeof(T));
  56. fPtr = SkTAddOffset<void>(fPtr, N * sizeof(T));
  57. this->write(remainder...);
  58. }
  59. template <typename... Args>
  60. void write(const GrVertexColor& color, const Args&... remainder) {
  61. this->write(color.fColor[0]);
  62. if (color.fWideColor) {
  63. this->write(color.fColor[1]);
  64. }
  65. this->write(remainder...);
  66. }
  67. template <typename T, typename... Args>
  68. void write(const Conditional<T>& val, const Args&... remainder) {
  69. if (val.fCondition) {
  70. this->write(val.fValue);
  71. }
  72. this->write(remainder...);
  73. }
  74. template <typename T, typename... Args>
  75. void write(const Skip<T>& val, const Args&... remainder) {
  76. fPtr = SkTAddOffset<void>(fPtr, sizeof(T));
  77. this->write(remainder...);
  78. }
  79. template <typename... Args>
  80. void write(const Sk4f& vector, const Args&... remainder) {
  81. float buffer[4];
  82. vector.store(buffer);
  83. this->write<float, 4>(buffer);
  84. this->write(remainder...);
  85. }
  86. void write() {}
  87. /**
  88. * Specialized utility for writing a four-vertices, with some data being replicated at each
  89. * vertex, and other data being the appropriate 2-components from an SkRect to construct a
  90. * triangle strip.
  91. *
  92. * writeQuad(A, B, C, ...) is similar to write(A, B, C, ...), except that:
  93. *
  94. * - Four sets of data will be written
  95. * - For any arguments of type TriStrip, a unique SkPoint will be written at each vertex,
  96. * in this order: left-top, left-bottom, right-top, right-bottom.
  97. */
  98. template <typename T>
  99. struct TriStrip { T l, t, r, b; };
  100. static TriStrip<float> TriStripFromRect(const SkRect& r) {
  101. return { r.fLeft, r.fTop, r.fRight, r.fBottom };
  102. }
  103. template <typename T>
  104. struct TriFan { T l, t, r, b; };
  105. static TriFan<float> TriFanFromRect(const SkRect& r) {
  106. return { r.fLeft, r.fTop, r.fRight, r.fBottom };
  107. }
  108. template <typename... Args>
  109. void writeQuad(const Args&... remainder) {
  110. this->writeQuadVert<0>(remainder...);
  111. this->writeQuadVert<1>(remainder...);
  112. this->writeQuadVert<2>(remainder...);
  113. this->writeQuadVert<3>(remainder...);
  114. }
  115. private:
  116. template <int corner, typename T, typename... Args>
  117. void writeQuadVert(const T& val, const Args&... remainder) {
  118. this->writeQuadValue<corner>(val);
  119. this->writeQuadVert<corner>(remainder...);
  120. }
  121. template <int corner>
  122. void writeQuadVert() {}
  123. template <int corner, typename T>
  124. void writeQuadValue(const T& val) {
  125. this->write(val);
  126. }
  127. template <int corner, typename T>
  128. void writeQuadValue(const TriStrip<T>& r) {
  129. switch (corner) {
  130. case 0: this->write(r.l, r.t); break;
  131. case 1: this->write(r.l, r.b); break;
  132. case 2: this->write(r.r, r.t); break;
  133. case 3: this->write(r.r, r.b); break;
  134. }
  135. }
  136. template <int corner, typename T>
  137. void writeQuadValue(const TriFan<T>& r) {
  138. switch (corner) {
  139. case 0: this->write(r.l, r.t); break;
  140. case 1: this->write(r.l, r.b); break;
  141. case 2: this->write(r.r, r.b); break;
  142. case 3: this->write(r.r, r.t); break;
  143. }
  144. }
  145. template <int corner>
  146. void writeQuadValue(const GrQuad& q) {
  147. this->write(q.point(corner));
  148. }
  149. };
  150. #endif