GrFillRRectOp.cpp 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821
  1. /*
  2. * Copyright 2018 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. #include "src/gpu/ops/GrFillRRectOp.h"
  8. #include "include/private/GrRecordingContext.h"
  9. #include "src/core/SkRRectPriv.h"
  10. #include "src/gpu/GrCaps.h"
  11. #include "src/gpu/GrGpuCommandBuffer.h"
  12. #include "src/gpu/GrMemoryPool.h"
  13. #include "src/gpu/GrOpFlushState.h"
  14. #include "src/gpu/GrRecordingContextPriv.h"
  15. #include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
  16. #include "src/gpu/glsl/GrGLSLGeometryProcessor.h"
  17. #include "src/gpu/glsl/GrGLSLVarying.h"
  18. #include "src/gpu/glsl/GrGLSLVertexGeoBuilder.h"
  19. // Hardware derivatives are not always accurate enough for highly elliptical corners. This method
  20. // checks to make sure the corners will still all look good if we use HW derivatives.
  21. static bool can_use_hw_derivatives_with_coverage(
  22. const GrShaderCaps&, const SkMatrix&, const SkRRect&);
  23. std::unique_ptr<GrFillRRectOp> GrFillRRectOp::Make(
  24. GrRecordingContext* ctx, GrAAType aaType, const SkMatrix& viewMatrix, const SkRRect& rrect,
  25. const GrCaps& caps, GrPaint&& paint) {
  26. if (!caps.instanceAttribSupport()) {
  27. return nullptr;
  28. }
  29. Flags flags = Flags::kNone;
  30. if (GrAAType::kCoverage == aaType) {
  31. // TODO: Support perspective in a follow-on CL. This shouldn't be difficult, since we
  32. // already use HW derivatives. The only trick will be adjusting the AA outset to account for
  33. // perspective. (i.e., outset = 0.5 * z.)
  34. if (viewMatrix.hasPerspective()) {
  35. return nullptr;
  36. }
  37. if (can_use_hw_derivatives_with_coverage(*caps.shaderCaps(), viewMatrix, rrect)) {
  38. // HW derivatives (more specifically, fwidth()) are consistently faster on all platforms
  39. // in coverage mode. We use them as long as the approximation will be accurate enough.
  40. flags |= Flags::kUseHWDerivatives;
  41. }
  42. } else {
  43. if (GrAAType::kMSAA == aaType) {
  44. if (!caps.sampleLocationsSupport() || !caps.shaderCaps()->sampleVariablesSupport()) {
  45. return nullptr;
  46. }
  47. }
  48. if (viewMatrix.hasPerspective()) {
  49. // HW derivatives are consistently slower on all platforms in sample mask mode. We
  50. // therefore only use them when there is perspective, since then we can't interpolate
  51. // the symbolic screen-space gradient.
  52. flags |= Flags::kUseHWDerivatives | Flags::kHasPerspective;
  53. }
  54. }
  55. // Produce a matrix that draws the round rect from normalized [-1, -1, +1, +1] space.
  56. float l = rrect.rect().left(), r = rrect.rect().right(),
  57. t = rrect.rect().top(), b = rrect.rect().bottom();
  58. SkMatrix m;
  59. // Unmap the normalized rect [-1, -1, +1, +1] back to [l, t, r, b].
  60. m.setScaleTranslate((r - l)/2, (b - t)/2, (l + r)/2, (t + b)/2);
  61. // Map to device space.
  62. m.postConcat(viewMatrix);
  63. SkRect devBounds;
  64. if (!(flags & Flags::kHasPerspective)) {
  65. // Since m is an affine matrix that maps the rect [-1, -1, +1, +1] into the shape's
  66. // device-space quad, it's quite simple to find the bounding rectangle:
  67. devBounds = SkRect::MakeXYWH(m.getTranslateX(), m.getTranslateY(), 0, 0);
  68. devBounds.outset(SkScalarAbs(m.getScaleX()) + SkScalarAbs(m.getSkewX()),
  69. SkScalarAbs(m.getSkewY()) + SkScalarAbs(m.getScaleY()));
  70. } else {
  71. viewMatrix.mapRect(&devBounds, rrect.rect());
  72. }
  73. if (GrAAType::kMSAA == aaType && caps.preferTrianglesOverSampleMask()) {
  74. // We are on a platform that prefers fine triangles instead of using the sample mask. See if
  75. // the round rect is large enough that it will be faster for us to send it off to the
  76. // default path renderer instead. The 200x200 threshold was arrived at using the
  77. // "shapes_rrect" benchmark on an ARM Galaxy S9.
  78. if (devBounds.height() * devBounds.width() > 200 * 200) {
  79. return nullptr;
  80. }
  81. }
  82. GrOpMemoryPool* pool = ctx->priv().opMemoryPool();
  83. return pool->allocate<GrFillRRectOp>(aaType, rrect, flags, m, std::move(paint), devBounds);
  84. }
  85. GrFillRRectOp::GrFillRRectOp(
  86. GrAAType aaType, const SkRRect& rrect, Flags flags,
  87. const SkMatrix& totalShapeMatrix, GrPaint&& paint, const SkRect& devBounds)
  88. : GrDrawOp(ClassID())
  89. , fAAType(aaType)
  90. , fOriginalColor(paint.getColor4f())
  91. , fLocalRect(rrect.rect())
  92. , fFlags(flags)
  93. , fProcessors(std::move(paint)) {
  94. SkASSERT((fFlags & Flags::kHasPerspective) == totalShapeMatrix.hasPerspective());
  95. this->setBounds(devBounds, GrOp::HasAABloat::kYes, GrOp::IsZeroArea::kNo);
  96. // Write the matrix attribs.
  97. const SkMatrix& m = totalShapeMatrix;
  98. if (!(fFlags & Flags::kHasPerspective)) {
  99. // Affine 2D transformation (float2x2 plus float2 translate).
  100. SkASSERT(!m.hasPerspective());
  101. this->writeInstanceData(m.getScaleX(), m.getSkewX(), m.getSkewY(), m.getScaleY());
  102. this->writeInstanceData(m.getTranslateX(), m.getTranslateY());
  103. } else {
  104. // Perspective float3x3 transformation matrix.
  105. SkASSERT(m.hasPerspective());
  106. m.get9(this->appendInstanceData<float>(9));
  107. }
  108. // Convert the radii to [-1, -1, +1, +1] space and write their attribs.
  109. Sk4f radiiX, radiiY;
  110. Sk4f::Load2(SkRRectPriv::GetRadiiArray(rrect), &radiiX, &radiiY);
  111. (radiiX * (2/rrect.width())).store(this->appendInstanceData<float>(4));
  112. (radiiY * (2/rrect.height())).store(this->appendInstanceData<float>(4));
  113. // We will write the color and local rect attribs during finalize().
  114. }
  115. GrProcessorSet::Analysis GrFillRRectOp::finalize(
  116. const GrCaps& caps, const GrAppliedClip* clip, bool hasMixedSampledCoverage,
  117. GrClampType clampType) {
  118. SkASSERT(1 == fInstanceCount);
  119. SkPMColor4f overrideColor;
  120. const GrProcessorSet::Analysis& analysis = fProcessors.finalize(
  121. fOriginalColor, GrProcessorAnalysisCoverage::kSingleChannel, clip,
  122. &GrUserStencilSettings::kUnused, hasMixedSampledCoverage, caps, clampType,
  123. &overrideColor);
  124. // Finish writing the instance attribs.
  125. SkPMColor4f finalColor = analysis.inputColorIsOverridden() ? overrideColor : fOriginalColor;
  126. if (!SkPMColor4fFitsInBytes(finalColor)) {
  127. fFlags |= Flags::kWideColor;
  128. uint32_t halfColor[2];
  129. SkFloatToHalf_finite_ftz(Sk4f::Load(finalColor.vec())).store(&halfColor);
  130. this->writeInstanceData(halfColor[0], halfColor[1]);
  131. } else {
  132. this->writeInstanceData(finalColor.toBytes_RGBA());
  133. }
  134. if (analysis.usesLocalCoords()) {
  135. this->writeInstanceData(fLocalRect);
  136. fFlags |= Flags::kHasLocalCoords;
  137. }
  138. fInstanceStride = fInstanceData.count();
  139. return analysis;
  140. }
  141. GrDrawOp::CombineResult GrFillRRectOp::onCombineIfPossible(GrOp* op, const GrCaps&) {
  142. const auto& that = *op->cast<GrFillRRectOp>();
  143. if (fFlags != that.fFlags || fProcessors != that.fProcessors ||
  144. fInstanceData.count() > std::numeric_limits<int>::max() - that.fInstanceData.count()) {
  145. return CombineResult::kCannotCombine;
  146. }
  147. fInstanceData.push_back_n(that.fInstanceData.count(), that.fInstanceData.begin());
  148. fInstanceCount += that.fInstanceCount;
  149. SkASSERT(fInstanceStride == that.fInstanceStride);
  150. return CombineResult::kMerged;
  151. }
  152. void GrFillRRectOp::onPrepare(GrOpFlushState* flushState) {
  153. if (void* instanceData = flushState->makeVertexSpace(fInstanceStride, fInstanceCount,
  154. &fInstanceBuffer, &fBaseInstance)) {
  155. SkASSERT(fInstanceStride * fInstanceCount == fInstanceData.count());
  156. memcpy(instanceData, fInstanceData.begin(), fInstanceData.count());
  157. }
  158. }
  159. class GrFillRRectOp::Processor : public GrGeometryProcessor {
  160. public:
  161. Processor(GrAAType aaType, Flags flags)
  162. : GrGeometryProcessor(kGrFillRRectOp_Processor_ClassID)
  163. , fAAType(aaType)
  164. , fFlags(flags) {
  165. int numVertexAttribs = (GrAAType::kCoverage == fAAType) ? 3 : 2;
  166. this->setVertexAttributes(kVertexAttribs, numVertexAttribs);
  167. if (!(flags & Flags::kHasPerspective)) {
  168. // Affine 2D transformation (float2x2 plus float2 translate).
  169. fInstanceAttribs.emplace_back("skew", kFloat4_GrVertexAttribType, kFloat4_GrSLType);
  170. fInstanceAttribs.emplace_back(
  171. "translate", kFloat2_GrVertexAttribType, kFloat2_GrSLType);
  172. } else {
  173. // Perspective float3x3 transformation matrix.
  174. fInstanceAttribs.emplace_back("persp_x", kFloat3_GrVertexAttribType, kFloat3_GrSLType);
  175. fInstanceAttribs.emplace_back("persp_y", kFloat3_GrVertexAttribType, kFloat3_GrSLType);
  176. fInstanceAttribs.emplace_back("persp_z", kFloat3_GrVertexAttribType, kFloat3_GrSLType);
  177. }
  178. fInstanceAttribs.emplace_back("radii_x", kFloat4_GrVertexAttribType, kFloat4_GrSLType);
  179. fInstanceAttribs.emplace_back("radii_y", kFloat4_GrVertexAttribType, kFloat4_GrSLType);
  180. fColorAttrib = &fInstanceAttribs.push_back(
  181. MakeColorAttribute("color", (flags & Flags::kWideColor)));
  182. if (fFlags & Flags::kHasLocalCoords) {
  183. fInstanceAttribs.emplace_back(
  184. "local_rect", kFloat4_GrVertexAttribType, kFloat4_GrSLType);
  185. }
  186. this->setInstanceAttributes(fInstanceAttribs.begin(), fInstanceAttribs.count());
  187. if (GrAAType::kMSAA == fAAType) {
  188. this->setWillUseCustomFeature(CustomFeatures::kSampleLocations);
  189. }
  190. }
  191. const char* name() const override { return "GrFillRRectOp::Processor"; }
  192. void getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
  193. b->add32(((uint32_t)fFlags << 16) | (uint32_t)fAAType);
  194. }
  195. GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override;
  196. private:
  197. static constexpr Attribute kVertexAttribs[] = {
  198. {"radii_selector", kFloat4_GrVertexAttribType, kFloat4_GrSLType},
  199. {"corner_and_radius_outsets", kFloat4_GrVertexAttribType, kFloat4_GrSLType},
  200. // Coverage only.
  201. {"aa_bloat_and_coverage", kFloat4_GrVertexAttribType, kFloat4_GrSLType}};
  202. const GrAAType fAAType;
  203. const Flags fFlags;
  204. SkSTArray<6, Attribute> fInstanceAttribs;
  205. const Attribute* fColorAttrib;
  206. class CoverageImpl;
  207. class MSAAImpl;
  208. };
  209. constexpr GrPrimitiveProcessor::Attribute GrFillRRectOp::Processor::kVertexAttribs[];
  210. // Our coverage geometry consists of an inset octagon with solid coverage, surrounded by linear
  211. // coverage ramps on the horizontal and vertical edges, and "arc coverage" pieces on the diagonal
  212. // edges. The Vertex struct tells the shader where to place its vertex within a normalized
  213. // ([l, t, r, b] = [-1, -1, +1, +1]) space, and how to calculate coverage. See onEmitCode.
  214. struct CoverageVertex {
  215. std::array<float, 4> fRadiiSelector;
  216. std::array<float, 2> fCorner;
  217. std::array<float, 2> fRadiusOutset;
  218. std::array<float, 2> fAABloatDirection;
  219. float fCoverage;
  220. float fIsLinearCoverage;
  221. };
  222. // This is the offset (when multiplied by radii) from the corners of a bounding box to the vertices
  223. // of its inscribed octagon. We draw the outside portion of arcs with quarter-octagons rather than
  224. // rectangles.
  225. static constexpr float kOctoOffset = 1/(1 + SK_ScalarRoot2Over2);
  226. static constexpr CoverageVertex kCoverageVertexData[] = {
  227. // Left inset edge.
  228. {{{0,0,0,1}}, {{-1,+1}}, {{0,-1}}, {{+1,0}}, 1, 1},
  229. {{{1,0,0,0}}, {{-1,-1}}, {{0,+1}}, {{+1,0}}, 1, 1},
  230. // Top inset edge.
  231. {{{1,0,0,0}}, {{-1,-1}}, {{+1,0}}, {{0,+1}}, 1, 1},
  232. {{{0,1,0,0}}, {{+1,-1}}, {{-1,0}}, {{0,+1}}, 1, 1},
  233. // Right inset edge.
  234. {{{0,1,0,0}}, {{+1,-1}}, {{0,+1}}, {{-1,0}}, 1, 1},
  235. {{{0,0,1,0}}, {{+1,+1}}, {{0,-1}}, {{-1,0}}, 1, 1},
  236. // Bottom inset edge.
  237. {{{0,0,1,0}}, {{+1,+1}}, {{-1,0}}, {{0,-1}}, 1, 1},
  238. {{{0,0,0,1}}, {{-1,+1}}, {{+1,0}}, {{0,-1}}, 1, 1},
  239. // Left outset edge.
  240. {{{0,0,0,1}}, {{-1,+1}}, {{0,-1}}, {{-1,0}}, 0, 1},
  241. {{{1,0,0,0}}, {{-1,-1}}, {{0,+1}}, {{-1,0}}, 0, 1},
  242. // Top outset edge.
  243. {{{1,0,0,0}}, {{-1,-1}}, {{+1,0}}, {{0,-1}}, 0, 1},
  244. {{{0,1,0,0}}, {{+1,-1}}, {{-1,0}}, {{0,-1}}, 0, 1},
  245. // Right outset edge.
  246. {{{0,1,0,0}}, {{+1,-1}}, {{0,+1}}, {{+1,0}}, 0, 1},
  247. {{{0,0,1,0}}, {{+1,+1}}, {{0,-1}}, {{+1,0}}, 0, 1},
  248. // Bottom outset edge.
  249. {{{0,0,1,0}}, {{+1,+1}}, {{-1,0}}, {{0,+1}}, 0, 1},
  250. {{{0,0,0,1}}, {{-1,+1}}, {{+1,0}}, {{0,+1}}, 0, 1},
  251. // Top-left corner.
  252. {{{1,0,0,0}}, {{-1,-1}}, {{ 0,+1}}, {{-1, 0}}, 0, 0},
  253. {{{1,0,0,0}}, {{-1,-1}}, {{ 0,+1}}, {{+1, 0}}, 1, 0},
  254. {{{1,0,0,0}}, {{-1,-1}}, {{+1, 0}}, {{ 0,+1}}, 1, 0},
  255. {{{1,0,0,0}}, {{-1,-1}}, {{+1, 0}}, {{ 0,-1}}, 0, 0},
  256. {{{1,0,0,0}}, {{-1,-1}}, {{+kOctoOffset,0}}, {{-1,-1}}, 0, 0},
  257. {{{1,0,0,0}}, {{-1,-1}}, {{0,+kOctoOffset}}, {{-1,-1}}, 0, 0},
  258. // Top-right corner.
  259. {{{0,1,0,0}}, {{+1,-1}}, {{-1, 0}}, {{ 0,-1}}, 0, 0},
  260. {{{0,1,0,0}}, {{+1,-1}}, {{-1, 0}}, {{ 0,+1}}, 1, 0},
  261. {{{0,1,0,0}}, {{+1,-1}}, {{ 0,+1}}, {{-1, 0}}, 1, 0},
  262. {{{0,1,0,0}}, {{+1,-1}}, {{ 0,+1}}, {{+1, 0}}, 0, 0},
  263. {{{0,1,0,0}}, {{+1,-1}}, {{0,+kOctoOffset}}, {{+1,-1}}, 0, 0},
  264. {{{0,1,0,0}}, {{+1,-1}}, {{-kOctoOffset,0}}, {{+1,-1}}, 0, 0},
  265. // Bottom-right corner.
  266. {{{0,0,1,0}}, {{+1,+1}}, {{ 0,-1}}, {{+1, 0}}, 0, 0},
  267. {{{0,0,1,0}}, {{+1,+1}}, {{ 0,-1}}, {{-1, 0}}, 1, 0},
  268. {{{0,0,1,0}}, {{+1,+1}}, {{-1, 0}}, {{ 0,-1}}, 1, 0},
  269. {{{0,0,1,0}}, {{+1,+1}}, {{-1, 0}}, {{ 0,+1}}, 0, 0},
  270. {{{0,0,1,0}}, {{+1,+1}}, {{-kOctoOffset,0}}, {{+1,+1}}, 0, 0},
  271. {{{0,0,1,0}}, {{+1,+1}}, {{0,-kOctoOffset}}, {{+1,+1}}, 0, 0},
  272. // Bottom-left corner.
  273. {{{0,0,0,1}}, {{-1,+1}}, {{+1, 0}}, {{ 0,+1}}, 0, 0},
  274. {{{0,0,0,1}}, {{-1,+1}}, {{+1, 0}}, {{ 0,-1}}, 1, 0},
  275. {{{0,0,0,1}}, {{-1,+1}}, {{ 0,-1}}, {{+1, 0}}, 1, 0},
  276. {{{0,0,0,1}}, {{-1,+1}}, {{ 0,-1}}, {{-1, 0}}, 0, 0},
  277. {{{0,0,0,1}}, {{-1,+1}}, {{0,-kOctoOffset}}, {{-1,+1}}, 0, 0},
  278. {{{0,0,0,1}}, {{-1,+1}}, {{+kOctoOffset,0}}, {{-1,+1}}, 0, 0}};
  279. GR_DECLARE_STATIC_UNIQUE_KEY(gCoverageVertexBufferKey);
  280. static constexpr uint16_t kCoverageIndexData[] = {
  281. // Inset octagon (solid coverage).
  282. 0, 1, 7,
  283. 1, 2, 7,
  284. 7, 2, 6,
  285. 2, 3, 6,
  286. 6, 3, 5,
  287. 3, 4, 5,
  288. // AA borders (linear coverage).
  289. 0, 1, 8, 1, 9, 8,
  290. 2, 3, 10, 3, 11, 10,
  291. 4, 5, 12, 5, 13, 12,
  292. 6, 7, 14, 7, 15, 14,
  293. // Top-left arc.
  294. 16, 17, 21,
  295. 17, 21, 18,
  296. 21, 18, 20,
  297. 18, 20, 19,
  298. // Top-right arc.
  299. 22, 23, 27,
  300. 23, 27, 24,
  301. 27, 24, 26,
  302. 24, 26, 25,
  303. // Bottom-right arc.
  304. 28, 29, 33,
  305. 29, 33, 30,
  306. 33, 30, 32,
  307. 30, 32, 31,
  308. // Bottom-left arc.
  309. 34, 35, 39,
  310. 35, 39, 36,
  311. 39, 36, 38,
  312. 36, 38, 37};
  313. GR_DECLARE_STATIC_UNIQUE_KEY(gCoverageIndexBufferKey);
  314. class GrFillRRectOp::Processor::CoverageImpl : public GrGLSLGeometryProcessor {
  315. void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
  316. const auto& proc = args.fGP.cast<Processor>();
  317. bool useHWDerivatives = (proc.fFlags & Flags::kUseHWDerivatives);
  318. SkASSERT(proc.vertexStride() == sizeof(CoverageVertex));
  319. GrGLSLVaryingHandler* varyings = args.fVaryingHandler;
  320. varyings->emitAttributes(proc);
  321. varyings->addPassThroughAttribute(*proc.fColorAttrib, args.fOutputColor,
  322. GrGLSLVaryingHandler::Interpolation::kCanBeFlat);
  323. // Emit the vertex shader.
  324. GrGLSLVertexBuilder* v = args.fVertBuilder;
  325. // Unpack vertex attribs.
  326. v->codeAppend("float2 corner = corner_and_radius_outsets.xy;");
  327. v->codeAppend("float2 radius_outset = corner_and_radius_outsets.zw;");
  328. v->codeAppend("float2 aa_bloat_direction = aa_bloat_and_coverage.xy;");
  329. v->codeAppend("float coverage = aa_bloat_and_coverage.z;");
  330. v->codeAppend("float is_linear_coverage = aa_bloat_and_coverage.w;");
  331. // Find the amount to bloat each edge for AA (in source space).
  332. v->codeAppend("float2 pixellength = inversesqrt("
  333. "float2(dot(skew.xz, skew.xz), dot(skew.yw, skew.yw)));");
  334. v->codeAppend("float4 normalized_axis_dirs = skew * pixellength.xyxy;");
  335. v->codeAppend("float2 axiswidths = (abs(normalized_axis_dirs.xy) + "
  336. "abs(normalized_axis_dirs.zw));");
  337. v->codeAppend("float2 aa_bloatradius = axiswidths * pixellength * .5;");
  338. // Identify our radii.
  339. v->codeAppend("float4 radii_and_neighbors = radii_selector"
  340. "* float4x4(radii_x, radii_y, radii_x.yxwz, radii_y.wzyx);");
  341. v->codeAppend("float2 radii = radii_and_neighbors.xy;");
  342. v->codeAppend("float2 neighbor_radii = radii_and_neighbors.zw;");
  343. v->codeAppend("if (any(greaterThan(aa_bloatradius, float2(1)))) {");
  344. // The rrect is more narrow than an AA coverage ramp. We can't draw as-is
  345. // or else opposite AA borders will overlap. Instead, fudge the size up to
  346. // the width of a coverage ramp, and then reduce total coverage to make
  347. // the rect appear more thin.
  348. v->codeAppend( "corner = max(abs(corner), aa_bloatradius) * sign(corner);");
  349. v->codeAppend( "coverage /= max(aa_bloatradius.x, 1) * max(aa_bloatradius.y, 1);");
  350. // Set radii to zero to ensure we take the "linear coverage" codepath.
  351. // (The "coverage" variable only has effect in the linear codepath.)
  352. v->codeAppend( "radii = float2(0);");
  353. v->codeAppend("}");
  354. v->codeAppend("if (any(lessThan(radii, aa_bloatradius * 1.25))) {");
  355. // The radii are very small. Demote this arc to a sharp 90 degree corner.
  356. v->codeAppend( "radii = aa_bloatradius;");
  357. // Snap octagon vertices to the corner of the bounding box.
  358. v->codeAppend( "radius_outset = floor(abs(radius_outset)) * radius_outset;");
  359. v->codeAppend( "is_linear_coverage = 1;");
  360. v->codeAppend("} else {");
  361. // Don't let radii get smaller than a pixel.
  362. v->codeAppend( "radii = clamp(radii, pixellength, 2 - pixellength);");
  363. v->codeAppend( "neighbor_radii = clamp(neighbor_radii, pixellength, 2 - pixellength);");
  364. // Don't let neighboring radii get closer together than 1/16 pixel.
  365. v->codeAppend( "float2 spacing = 2 - radii - neighbor_radii;");
  366. v->codeAppend( "float2 extra_pad = max(pixellength * .0625 - spacing, float2(0));");
  367. v->codeAppend( "radii -= extra_pad * .5;");
  368. v->codeAppend("}");
  369. // Find our vertex position, adjusted for radii and bloated for AA. Our rect is drawn in
  370. // normalized [-1,-1,+1,+1] space.
  371. v->codeAppend("float2 aa_outset = aa_bloat_direction.xy * aa_bloatradius;");
  372. v->codeAppend("float2 vertexpos = corner + radius_outset * radii + aa_outset;");
  373. // Emit transforms.
  374. GrShaderVar localCoord("", kFloat2_GrSLType);
  375. if (proc.fFlags & Flags::kHasLocalCoords) {
  376. v->codeAppend("float2 localcoord = (local_rect.xy * (1 - vertexpos) + "
  377. "local_rect.zw * (1 + vertexpos)) * .5;");
  378. localCoord.set(kFloat2_GrSLType, "localcoord");
  379. }
  380. this->emitTransforms(v, varyings, args.fUniformHandler, localCoord,
  381. args.fFPCoordTransformHandler);
  382. // Transform to device space.
  383. SkASSERT(!(proc.fFlags & Flags::kHasPerspective));
  384. v->codeAppend("float2x2 skewmatrix = float2x2(skew.xy, skew.zw);");
  385. v->codeAppend("float2 devcoord = vertexpos * skewmatrix + translate;");
  386. gpArgs->fPositionVar.set(kFloat2_GrSLType, "devcoord");
  387. // Setup interpolants for coverage.
  388. GrGLSLVarying arcCoord(useHWDerivatives ? kFloat2_GrSLType : kFloat4_GrSLType);
  389. varyings->addVarying("arccoord", &arcCoord);
  390. v->codeAppend("if (0 != is_linear_coverage) {");
  391. // We are a non-corner piece: Set x=0 to indicate built-in coverage, and
  392. // interpolate linear coverage across y.
  393. v->codeAppendf( "%s.xy = float2(0, coverage);", arcCoord.vsOut());
  394. v->codeAppend("} else {");
  395. // Find the normalized arc coordinates for our corner ellipse.
  396. // (i.e., the coordinate system where x^2 + y^2 == 1).
  397. v->codeAppend( "float2 arccoord = 1 - abs(radius_outset) + aa_outset/radii * corner;");
  398. // We are a corner piece: Interpolate the arc coordinates for coverage.
  399. // Emit x+1 to ensure no pixel in the arc has a x value of 0 (since x=0
  400. // instructs the fragment shader to use linear coverage).
  401. v->codeAppendf( "%s.xy = float2(arccoord.x+1, arccoord.y);", arcCoord.vsOut());
  402. if (!useHWDerivatives) {
  403. // The gradient is order-1: Interpolate it across arccoord.zw.
  404. v->codeAppendf("float2x2 derivatives = inverse(skewmatrix);");
  405. v->codeAppendf("%s.zw = derivatives * (arccoord/radii * 2);", arcCoord.vsOut());
  406. }
  407. v->codeAppend("}");
  408. // Emit the fragment shader.
  409. GrGLSLFPFragmentBuilder* f = args.fFragBuilder;
  410. f->codeAppendf("float x_plus_1=%s.x, y=%s.y;", arcCoord.fsIn(), arcCoord.fsIn());
  411. f->codeAppendf("half coverage;");
  412. f->codeAppendf("if (0 == x_plus_1) {");
  413. f->codeAppendf( "coverage = half(y);"); // We are a non-arc pixel (linear coverage).
  414. f->codeAppendf("} else {");
  415. f->codeAppendf( "float fn = x_plus_1 * (x_plus_1 - 2);"); // fn = (x+1)*(x-1) = x^2-1
  416. f->codeAppendf( "fn = fma(y,y, fn);"); // fn = x^2 + y^2 - 1
  417. if (useHWDerivatives) {
  418. f->codeAppendf("float fnwidth = fwidth(fn);");
  419. } else {
  420. // The gradient is interpolated across arccoord.zw.
  421. f->codeAppendf("float gx=%s.z, gy=%s.w;", arcCoord.fsIn(), arcCoord.fsIn());
  422. f->codeAppendf("float fnwidth = abs(gx) + abs(gy);");
  423. }
  424. f->codeAppendf( "half d = half(fn/fnwidth);");
  425. f->codeAppendf( "coverage = clamp(.5 - d, 0, 1);");
  426. f->codeAppendf("}");
  427. f->codeAppendf("%s = half4(coverage);", args.fOutputCoverage);
  428. }
  429. void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor&,
  430. FPCoordTransformIter&& transformIter) override {
  431. this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter);
  432. }
  433. };
  434. // Our MSAA geometry consists of an inset octagon with full sample mask coverage, circumscribed
  435. // by a larger octagon that modifies the sample mask for the arc at each corresponding corner.
  436. struct MSAAVertex {
  437. std::array<float, 4> fRadiiSelector;
  438. std::array<float, 2> fCorner;
  439. std::array<float, 2> fRadiusOutset;
  440. };
  441. static constexpr MSAAVertex kMSAAVertexData[] = {
  442. // Left edge. (Negative radii selector indicates this is not an arc section.)
  443. {{{0,0,0,-1}}, {{-1,+1}}, {{0,-1}}},
  444. {{{-1,0,0,0}}, {{-1,-1}}, {{0,+1}}},
  445. // Top edge.
  446. {{{-1,0,0,0}}, {{-1,-1}}, {{+1,0}}},
  447. {{{0,-1,0,0}}, {{+1,-1}}, {{-1,0}}},
  448. // Right edge.
  449. {{{0,-1,0,0}}, {{+1,-1}}, {{0,+1}}},
  450. {{{0,0,-1,0}}, {{+1,+1}}, {{0,-1}}},
  451. // Bottom edge.
  452. {{{0,0,-1,0}}, {{+1,+1}}, {{-1,0}}},
  453. {{{0,0,0,-1}}, {{-1,+1}}, {{+1,0}}},
  454. // Top-left corner.
  455. {{{1,0,0,0}}, {{-1,-1}}, {{0,+1}}},
  456. {{{1,0,0,0}}, {{-1,-1}}, {{0,+kOctoOffset}}},
  457. {{{1,0,0,0}}, {{-1,-1}}, {{+1,0}}},
  458. {{{1,0,0,0}}, {{-1,-1}}, {{+kOctoOffset,0}}},
  459. // Top-right corner.
  460. {{{0,1,0,0}}, {{+1,-1}}, {{-1,0}}},
  461. {{{0,1,0,0}}, {{+1,-1}}, {{-kOctoOffset,0}}},
  462. {{{0,1,0,0}}, {{+1,-1}}, {{0,+1}}},
  463. {{{0,1,0,0}}, {{+1,-1}}, {{0,+kOctoOffset}}},
  464. // Bottom-right corner.
  465. {{{0,0,1,0}}, {{+1,+1}}, {{0,-1}}},
  466. {{{0,0,1,0}}, {{+1,+1}}, {{0,-kOctoOffset}}},
  467. {{{0,0,1,0}}, {{+1,+1}}, {{-1,0}}},
  468. {{{0,0,1,0}}, {{+1,+1}}, {{-kOctoOffset,0}}},
  469. // Bottom-left corner.
  470. {{{0,0,0,1}}, {{-1,+1}}, {{+1,0}}},
  471. {{{0,0,0,1}}, {{-1,+1}}, {{+kOctoOffset,0}}},
  472. {{{0,0,0,1}}, {{-1,+1}}, {{0,-1}}},
  473. {{{0,0,0,1}}, {{-1,+1}}, {{0,-kOctoOffset}}}};
  474. GR_DECLARE_STATIC_UNIQUE_KEY(gMSAAVertexBufferKey);
  475. static constexpr uint16_t kMSAAIndexData[] = {
  476. // Inset octagon. (Full sample mask.)
  477. 0, 1, 2,
  478. 0, 2, 3,
  479. 0, 3, 6,
  480. 3, 4, 5,
  481. 3, 5, 6,
  482. 6, 7, 0,
  483. // Top-left arc. (Sample mask is set to the arc.)
  484. 8, 9, 10,
  485. 9, 11, 10,
  486. // Top-right arc.
  487. 12, 13, 14,
  488. 13, 15, 14,
  489. // Bottom-right arc.
  490. 16, 17, 18,
  491. 17, 19, 18,
  492. // Bottom-left arc.
  493. 20, 21, 22,
  494. 21, 23, 22};
  495. GR_DECLARE_STATIC_UNIQUE_KEY(gMSAAIndexBufferKey);
  496. class GrFillRRectOp::Processor::MSAAImpl : public GrGLSLGeometryProcessor {
  497. void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
  498. const auto& proc = args.fGP.cast<Processor>();
  499. bool useHWDerivatives = (proc.fFlags & Flags::kUseHWDerivatives);
  500. bool hasPerspective = (proc.fFlags & Flags::kHasPerspective);
  501. bool hasLocalCoords = (proc.fFlags & Flags::kHasLocalCoords);
  502. SkASSERT(useHWDerivatives == hasPerspective);
  503. SkASSERT(proc.vertexStride() == sizeof(MSAAVertex));
  504. // Emit the vertex shader.
  505. GrGLSLVertexBuilder* v = args.fVertBuilder;
  506. GrGLSLVaryingHandler* varyings = args.fVaryingHandler;
  507. varyings->emitAttributes(proc);
  508. varyings->addPassThroughAttribute(*proc.fColorAttrib, args.fOutputColor,
  509. GrGLSLVaryingHandler::Interpolation::kCanBeFlat);
  510. // Unpack vertex attribs.
  511. v->codeAppendf("float2 corner = corner_and_radius_outsets.xy;");
  512. v->codeAppendf("float2 radius_outset = corner_and_radius_outsets.zw;");
  513. // Identify our radii.
  514. v->codeAppend("float2 radii;");
  515. v->codeAppend("radii.x = dot(radii_selector, radii_x);");
  516. v->codeAppend("radii.y = dot(radii_selector, radii_y);");
  517. v->codeAppendf("bool is_arc_section = (radii.x > 0);");
  518. v->codeAppendf("radii = abs(radii);");
  519. // Find our vertex position, adjusted for radii. Our rect is drawn in normalized
  520. // [-1,-1,+1,+1] space.
  521. v->codeAppend("float2 vertexpos = corner + radius_outset * radii;");
  522. // Emit transforms.
  523. GrShaderVar localCoord("", kFloat2_GrSLType);
  524. if (hasLocalCoords) {
  525. v->codeAppend("float2 localcoord = (local_rect.xy * (1 - vertexpos) + "
  526. "local_rect.zw * (1 + vertexpos)) * .5;");
  527. localCoord.set(kFloat2_GrSLType, "localcoord");
  528. }
  529. this->emitTransforms(v, varyings, args.fUniformHandler, localCoord,
  530. args.fFPCoordTransformHandler);
  531. // Transform to device space.
  532. if (!hasPerspective) {
  533. v->codeAppend("float2x2 skewmatrix = float2x2(skew.xy, skew.zw);");
  534. v->codeAppend("float2 devcoord = vertexpos * skewmatrix + translate;");
  535. gpArgs->fPositionVar.set(kFloat2_GrSLType, "devcoord");
  536. } else {
  537. v->codeAppend("float3x3 persp_matrix = float3x3(persp_x, persp_y, persp_z);");
  538. v->codeAppend("float3 devcoord = float3(vertexpos, 1) * persp_matrix;");
  539. gpArgs->fPositionVar.set(kFloat3_GrSLType, "devcoord");
  540. }
  541. // Determine normalized arc coordinates for the implicit function.
  542. GrGLSLVarying arcCoord((useHWDerivatives) ? kFloat2_GrSLType : kFloat4_GrSLType);
  543. varyings->addVarying("arccoord", &arcCoord);
  544. v->codeAppendf("if (is_arc_section) {");
  545. v->codeAppendf( "%s.xy = 1 - abs(radius_outset);", arcCoord.vsOut());
  546. if (!useHWDerivatives) {
  547. // The gradient is order-1: Interpolate it across arccoord.zw.
  548. // This doesn't work with perspective.
  549. SkASSERT(!hasPerspective);
  550. v->codeAppendf("float2x2 derivatives = inverse(skewmatrix);");
  551. v->codeAppendf("%s.zw = derivatives * (%s.xy/radii * corner * 2);",
  552. arcCoord.vsOut(), arcCoord.vsOut());
  553. }
  554. v->codeAppendf("} else {");
  555. if (useHWDerivatives) {
  556. v->codeAppendf("%s = float2(0);", arcCoord.vsOut());
  557. } else {
  558. v->codeAppendf("%s = float4(0);", arcCoord.vsOut());
  559. }
  560. v->codeAppendf("}");
  561. // Emit the fragment shader.
  562. GrGLSLFPFragmentBuilder* f = args.fFragBuilder;
  563. f->codeAppendf("%s = half4(1);", args.fOutputCoverage);
  564. // If x,y == 0, then we are drawing a triangle that does not track an arc.
  565. f->codeAppendf("if (float2(0) != %s.xy) {", arcCoord.fsIn());
  566. f->codeAppendf( "float fn = dot(%s.xy, %s.xy) - 1;", arcCoord.fsIn(), arcCoord.fsIn());
  567. if (GrAAType::kMSAA == proc.fAAType) {
  568. using ScopeFlags = GrGLSLFPFragmentBuilder::ScopeFlags;
  569. if (!useHWDerivatives) {
  570. f->codeAppendf("float2 grad = %s.zw;", arcCoord.fsIn());
  571. f->applyFnToMultisampleMask("fn", "grad", ScopeFlags::kInsidePerPrimitiveBranch);
  572. } else {
  573. f->applyFnToMultisampleMask("fn", nullptr, ScopeFlags::kInsidePerPrimitiveBranch);
  574. }
  575. } else {
  576. f->codeAppendf("if (fn > 0) {");
  577. f->codeAppendf( "%s = half4(0);", args.fOutputCoverage);
  578. f->codeAppendf("}");
  579. }
  580. f->codeAppendf("}");
  581. }
  582. void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor&,
  583. FPCoordTransformIter&& transformIter) override {
  584. this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter);
  585. }
  586. };
  587. GrGLSLPrimitiveProcessor* GrFillRRectOp::Processor::createGLSLInstance(
  588. const GrShaderCaps&) const {
  589. if (GrAAType::kCoverage != fAAType) {
  590. return new MSAAImpl();
  591. }
  592. return new CoverageImpl();
  593. }
  594. void GrFillRRectOp::onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) {
  595. if (!fInstanceBuffer) {
  596. return; // Setup failed.
  597. }
  598. sk_sp<const GrBuffer> indexBuffer, vertexBuffer;
  599. int indexCount;
  600. if (GrAAType::kCoverage == fAAType) {
  601. GR_DEFINE_STATIC_UNIQUE_KEY(gCoverageIndexBufferKey);
  602. indexBuffer = flushState->resourceProvider()->findOrMakeStaticBuffer(
  603. GrGpuBufferType::kIndex, sizeof(kCoverageIndexData), kCoverageIndexData,
  604. gCoverageIndexBufferKey);
  605. GR_DEFINE_STATIC_UNIQUE_KEY(gCoverageVertexBufferKey);
  606. vertexBuffer = flushState->resourceProvider()->findOrMakeStaticBuffer(
  607. GrGpuBufferType::kVertex, sizeof(kCoverageVertexData), kCoverageVertexData,
  608. gCoverageVertexBufferKey);
  609. indexCount = SK_ARRAY_COUNT(kCoverageIndexData);
  610. } else {
  611. GR_DEFINE_STATIC_UNIQUE_KEY(gMSAAIndexBufferKey);
  612. indexBuffer = flushState->resourceProvider()->findOrMakeStaticBuffer(
  613. GrGpuBufferType::kIndex, sizeof(kMSAAIndexData), kMSAAIndexData,
  614. gMSAAIndexBufferKey);
  615. GR_DEFINE_STATIC_UNIQUE_KEY(gMSAAVertexBufferKey);
  616. vertexBuffer = flushState->resourceProvider()->findOrMakeStaticBuffer(
  617. GrGpuBufferType::kVertex, sizeof(kMSAAVertexData), kMSAAVertexData,
  618. gMSAAVertexBufferKey);
  619. indexCount = SK_ARRAY_COUNT(kMSAAIndexData);
  620. }
  621. if (!indexBuffer || !vertexBuffer) {
  622. return;
  623. }
  624. Processor proc(fAAType, fFlags);
  625. SkASSERT(proc.instanceStride() == (size_t)fInstanceStride);
  626. GrPipeline::InitArgs initArgs;
  627. if (GrAAType::kMSAA == fAAType) {
  628. initArgs.fInputFlags = GrPipeline::InputFlags::kHWAntialias;
  629. }
  630. initArgs.fCaps = &flushState->caps();
  631. initArgs.fDstProxy = flushState->drawOpArgs().fDstProxy;
  632. initArgs.fOutputSwizzle = flushState->drawOpArgs().fOutputSwizzle;
  633. auto clip = flushState->detachAppliedClip();
  634. GrPipeline::FixedDynamicState fixedDynamicState(clip.scissorState().rect());
  635. GrPipeline pipeline(initArgs, std::move(fProcessors), std::move(clip));
  636. GrMesh mesh(GrPrimitiveType::kTriangles);
  637. mesh.setIndexedInstanced(
  638. std::move(indexBuffer), indexCount, fInstanceBuffer, fInstanceCount, fBaseInstance,
  639. GrPrimitiveRestart::kNo);
  640. mesh.setVertexData(std::move(vertexBuffer));
  641. flushState->rtCommandBuffer()->draw(
  642. proc, pipeline, &fixedDynamicState, nullptr, &mesh, 1, this->bounds());
  643. }
  644. // Will the given corner look good if we use HW derivatives?
  645. static bool can_use_hw_derivatives_with_coverage(const Sk2f& devScale, const Sk2f& cornerRadii) {
  646. Sk2f devRadii = devScale * cornerRadii;
  647. if (devRadii[1] < devRadii[0]) {
  648. devRadii = SkNx_shuffle<1,0>(devRadii);
  649. }
  650. float minDevRadius = SkTMax(devRadii[0], 1.f); // Shader clamps radius at a minimum of 1.
  651. // Is the gradient smooth enough for this corner look ok if we use hardware derivatives?
  652. // This threshold was arrived at subjevtively on an NVIDIA chip.
  653. return minDevRadius * minDevRadius * 5 > devRadii[1];
  654. }
  655. static bool can_use_hw_derivatives_with_coverage(
  656. const Sk2f& devScale, const SkVector& cornerRadii) {
  657. return can_use_hw_derivatives_with_coverage(devScale, Sk2f::Load(&cornerRadii));
  658. }
  659. // Will the given round rect look good if we use HW derivatives?
  660. static bool can_use_hw_derivatives_with_coverage(
  661. const GrShaderCaps& shaderCaps, const SkMatrix& viewMatrix, const SkRRect& rrect) {
  662. if (!shaderCaps.shaderDerivativeSupport()) {
  663. return false;
  664. }
  665. Sk2f x = Sk2f(viewMatrix.getScaleX(), viewMatrix.getSkewX());
  666. Sk2f y = Sk2f(viewMatrix.getSkewY(), viewMatrix.getScaleY());
  667. Sk2f devScale = (x*x + y*y).sqrt();
  668. switch (rrect.getType()) {
  669. case SkRRect::kEmpty_Type:
  670. case SkRRect::kRect_Type:
  671. return true;
  672. case SkRRect::kOval_Type:
  673. case SkRRect::kSimple_Type:
  674. return can_use_hw_derivatives_with_coverage(devScale, rrect.getSimpleRadii());
  675. case SkRRect::kNinePatch_Type: {
  676. Sk2f r0 = Sk2f::Load(SkRRectPriv::GetRadiiArray(rrect));
  677. Sk2f r1 = Sk2f::Load(SkRRectPriv::GetRadiiArray(rrect) + 2);
  678. Sk2f minRadii = Sk2f::Min(r0, r1);
  679. Sk2f maxRadii = Sk2f::Max(r0, r1);
  680. return can_use_hw_derivatives_with_coverage(devScale, Sk2f(minRadii[0], maxRadii[1])) &&
  681. can_use_hw_derivatives_with_coverage(devScale, Sk2f(maxRadii[0], minRadii[1]));
  682. }
  683. case SkRRect::kComplex_Type: {
  684. for (int i = 0; i < 4; ++i) {
  685. auto corner = static_cast<SkRRect::Corner>(i);
  686. if (!can_use_hw_derivatives_with_coverage(devScale, rrect.radii(corner))) {
  687. return false;
  688. }
  689. }
  690. return true;
  691. }
  692. }
  693. SK_ABORT("Invalid round rect type.");
  694. return false; // Add this return to keep GCC happy.
  695. }