convexpolyeffect.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. /*
  2. * Copyright 2014 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. // This test only works with the GPU backend.
  8. #include "gm/gm.h"
  9. #include "include/core/SkBlendMode.h"
  10. #include "include/core/SkCanvas.h"
  11. #include "include/core/SkMatrix.h"
  12. #include "include/core/SkPaint.h"
  13. #include "include/core/SkPath.h"
  14. #include "include/core/SkPoint.h"
  15. #include "include/core/SkRect.h"
  16. #include "include/core/SkRefCnt.h"
  17. #include "include/core/SkScalar.h"
  18. #include "include/core/SkSize.h"
  19. #include "include/core/SkString.h"
  20. #include "include/core/SkTypes.h"
  21. #include "include/gpu/GrContext.h"
  22. #include "include/private/GrRecordingContext.h"
  23. #include "include/private/GrSharedEnums.h"
  24. #include "include/private/GrTypesPriv.h"
  25. #include "include/private/SkColorData.h"
  26. #include "src/core/SkPointPriv.h"
  27. #include "src/core/SkTLList.h"
  28. #include "src/gpu/GrCaps.h"
  29. #include "src/gpu/GrDefaultGeoProcFactory.h"
  30. #include "src/gpu/GrFragmentProcessor.h"
  31. #include "src/gpu/GrGeometryProcessor.h"
  32. #include "src/gpu/GrMemoryPool.h"
  33. #include "src/gpu/GrOpFlushState.h"
  34. #include "src/gpu/GrPaint.h"
  35. #include "src/gpu/GrProcessorAnalysis.h"
  36. #include "src/gpu/GrProcessorSet.h"
  37. #include "src/gpu/GrRecordingContextPriv.h"
  38. #include "src/gpu/GrRenderTargetContext.h"
  39. #include "src/gpu/GrRenderTargetContextPriv.h"
  40. #include "src/gpu/GrUserStencilSettings.h"
  41. #include "src/gpu/effects/GrConvexPolyEffect.h"
  42. #include "src/gpu/effects/GrPorterDuffXferProcessor.h"
  43. #include "src/gpu/ops/GrDrawOp.h"
  44. #include "src/gpu/ops/GrMeshDrawOp.h"
  45. #include "src/gpu/ops/GrOp.h"
  46. #include <memory>
  47. #include <utility>
  48. class GrAppliedClip;
  49. /** outset rendered rect to visualize anti-aliased poly edges */
  50. static SkRect outset(const SkRect& unsorted) {
  51. SkRect r = unsorted;
  52. r.outset(5.f, 5.f);
  53. return r;
  54. }
  55. /** sorts a rect */
  56. static SkRect sorted_rect(const SkRect& unsorted) {
  57. SkRect r = unsorted;
  58. r.sort();
  59. return r;
  60. }
  61. namespace skiagm {
  62. class PolyBoundsOp : public GrMeshDrawOp {
  63. public:
  64. DEFINE_OP_CLASS_ID
  65. static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
  66. GrPaint&& paint,
  67. const SkRect& rect) {
  68. GrOpMemoryPool* pool = context->priv().opMemoryPool();
  69. return pool->allocate<PolyBoundsOp>(std::move(paint), rect);
  70. }
  71. const char* name() const override { return "PolyBoundsOp"; }
  72. void visitProxies(const VisitProxyFunc& func) const override {
  73. fProcessors.visitProxies(func);
  74. }
  75. FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
  76. GrProcessorSet::Analysis finalize(
  77. const GrCaps& caps, const GrAppliedClip* clip, bool hasMixedSampledCoverage,
  78. GrClampType clampType) override {
  79. return fProcessors.finalize(
  80. fColor, GrProcessorAnalysisCoverage::kNone, clip, &GrUserStencilSettings::kUnused,
  81. hasMixedSampledCoverage, caps, clampType, &fColor);
  82. }
  83. private:
  84. friend class ::GrOpMemoryPool; // for ctor
  85. PolyBoundsOp(GrPaint&& paint, const SkRect& rect)
  86. : INHERITED(ClassID())
  87. , fColor(paint.getColor4f())
  88. , fProcessors(std::move(paint))
  89. , fRect(outset(rect)) {
  90. this->setBounds(sorted_rect(fRect), HasAABloat::kNo, IsZeroArea::kNo);
  91. }
  92. void onPrepareDraws(Target* target) override {
  93. using namespace GrDefaultGeoProcFactory;
  94. Color color(fColor);
  95. sk_sp<GrGeometryProcessor> gp(GrDefaultGeoProcFactory::Make(
  96. target->caps().shaderCaps(),
  97. color,
  98. Coverage::kSolid_Type,
  99. LocalCoords::kUnused_Type,
  100. SkMatrix::I()));
  101. SkASSERT(gp->vertexStride() == sizeof(SkPoint));
  102. QuadHelper helper(target, sizeof(SkPoint), 1);
  103. SkPoint* verts = reinterpret_cast<SkPoint*>(helper.vertices());
  104. if (!verts) {
  105. return;
  106. }
  107. SkPointPriv::SetRectTriStrip(verts, fRect, sizeof(SkPoint));
  108. helper.recordDraw(target, std::move(gp));
  109. }
  110. void onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) override {
  111. flushState->executeDrawsAndUploadsForMeshDrawOp(this, chainBounds, std::move(fProcessors));
  112. }
  113. SkPMColor4f fColor;
  114. GrProcessorSet fProcessors;
  115. SkRect fRect;
  116. typedef GrMeshDrawOp INHERITED;
  117. };
  118. /**
  119. * This GM directly exercises a GrProcessor that draws convex polygons.
  120. */
  121. class ConvexPolyEffect : public GpuGM {
  122. public:
  123. ConvexPolyEffect() {
  124. this->setBGColor(0xFFFFFFFF);
  125. }
  126. protected:
  127. SkString onShortName() override {
  128. return SkString("convex_poly_effect");
  129. }
  130. SkISize onISize() override {
  131. return SkISize::Make(720, 800);
  132. }
  133. void onOnceBeforeDraw() override {
  134. SkPath tri;
  135. tri.moveTo(5.f, 5.f);
  136. tri.lineTo(100.f, 20.f);
  137. tri.lineTo(15.f, 100.f);
  138. fPaths.addToTail(tri);
  139. fPaths.addToTail(SkPath())->reverseAddPath(tri);
  140. tri.close();
  141. fPaths.addToTail(tri);
  142. SkPath ngon;
  143. constexpr SkScalar kRadius = 50.f;
  144. const SkPoint center = { kRadius, kRadius };
  145. for (int i = 0; i < GrConvexPolyEffect::kMaxEdges; ++i) {
  146. SkScalar angle = 2 * SK_ScalarPI * i / GrConvexPolyEffect::kMaxEdges;
  147. SkPoint point = { SkScalarCos(angle), SkScalarSin(angle) };
  148. point.scale(kRadius);
  149. point = center + point;
  150. if (0 == i) {
  151. ngon.moveTo(point);
  152. } else {
  153. ngon.lineTo(point);
  154. }
  155. }
  156. fPaths.addToTail(ngon);
  157. SkMatrix scaleM;
  158. scaleM.setScale(1.1f, 0.4f);
  159. ngon.transform(scaleM);
  160. fPaths.addToTail(ngon);
  161. SkPath linePath;
  162. linePath.moveTo(5.f, 5.f);
  163. linePath.lineTo(6.f, 6.f);
  164. fPaths.addToTail(linePath);
  165. // integer edges
  166. fRects.addToTail(SkRect::MakeLTRB(5.f, 1.f, 30.f, 25.f));
  167. // half-integer edges
  168. fRects.addToTail(SkRect::MakeLTRB(5.5f, 0.5f, 29.5f, 24.5f));
  169. // vertically/horizontally thin rects that cover pixel centers
  170. fRects.addToTail(SkRect::MakeLTRB(5.25f, 0.5f, 5.75f, 24.5f));
  171. fRects.addToTail(SkRect::MakeLTRB(5.5f, 0.5f, 29.5f, 0.75f));
  172. // vertically/horizontally thin rects that don't cover pixel centers
  173. fRects.addToTail(SkRect::MakeLTRB(5.55f, 0.5f, 5.75f, 24.5f));
  174. fRects.addToTail(SkRect::MakeLTRB(5.5f, .05f, 29.5f, .25f));
  175. // small in x and y
  176. fRects.addToTail(SkRect::MakeLTRB(5.05f, .55f, 5.45f, .85f));
  177. // inverted in x and y
  178. fRects.addToTail(SkRect::MakeLTRB(100.f, 50.5f, 5.f, 0.5f));
  179. }
  180. void onDraw(GrContext* context, GrRenderTargetContext* renderTargetContext,
  181. SkCanvas* canvas) override {
  182. SkScalar y = 0;
  183. constexpr SkScalar kDX = 12.f;
  184. for (PathList::Iter iter(fPaths, PathList::Iter::kHead_IterStart);
  185. iter.get();
  186. iter.next()) {
  187. const SkPath* path = iter.get();
  188. SkScalar x = 0;
  189. for (int et = 0; et < kGrClipEdgeTypeCnt; ++et) {
  190. const SkMatrix m = SkMatrix::MakeTrans(x, y);
  191. SkPath p;
  192. path->transform(m, &p);
  193. GrClipEdgeType edgeType = (GrClipEdgeType) et;
  194. std::unique_ptr<GrFragmentProcessor> fp(GrConvexPolyEffect::Make(edgeType, p));
  195. if (!fp) {
  196. continue;
  197. }
  198. GrPaint grPaint;
  199. grPaint.setColor4f({ 0, 0, 0, 1.f });
  200. grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
  201. grPaint.addCoverageFragmentProcessor(std::move(fp));
  202. std::unique_ptr<GrDrawOp> op =
  203. PolyBoundsOp::Make(context, std::move(grPaint), p.getBounds());
  204. renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
  205. x += SkScalarCeilToScalar(path->getBounds().width() + kDX);
  206. }
  207. // Draw AA and non AA paths using normal API for reference.
  208. canvas->save();
  209. canvas->translate(x, y);
  210. SkPaint paint;
  211. canvas->drawPath(*path, paint);
  212. canvas->translate(path->getBounds().width() + 10.f, 0);
  213. paint.setAntiAlias(true);
  214. canvas->drawPath(*path, paint);
  215. canvas->restore();
  216. y += SkScalarCeilToScalar(path->getBounds().height() + 20.f);
  217. }
  218. for (RectList::Iter iter(fRects, RectList::Iter::kHead_IterStart);
  219. iter.get();
  220. iter.next()) {
  221. SkScalar x = 0;
  222. for (int et = 0; et < kGrClipEdgeTypeCnt; ++et) {
  223. SkRect rect = *iter.get();
  224. rect.offset(x, y);
  225. GrClipEdgeType edgeType = (GrClipEdgeType) et;
  226. std::unique_ptr<GrFragmentProcessor> fp(GrConvexPolyEffect::Make(edgeType, rect));
  227. if (!fp) {
  228. continue;
  229. }
  230. GrPaint grPaint;
  231. grPaint.setColor4f({ 0, 0, 0, 1.f });
  232. grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
  233. grPaint.addCoverageFragmentProcessor(std::move(fp));
  234. std::unique_ptr<GrDrawOp> op = PolyBoundsOp::Make(context, std::move(grPaint),
  235. rect);
  236. renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
  237. x += SkScalarCeilToScalar(rect.width() + kDX);
  238. }
  239. // Draw rect without and with AA using normal API for reference
  240. canvas->save();
  241. canvas->translate(x, y);
  242. SkPaint paint;
  243. canvas->drawRect(*iter.get(), paint);
  244. x += SkScalarCeilToScalar(iter.get()->width() + kDX);
  245. paint.setAntiAlias(true);
  246. canvas->drawRect(*iter.get(), paint);
  247. canvas->restore();
  248. y += SkScalarCeilToScalar(iter.get()->height() + 20.f);
  249. }
  250. }
  251. private:
  252. typedef SkTLList<SkPath, 1> PathList;
  253. typedef SkTLList<SkRect, 1> RectList;
  254. PathList fPaths;
  255. RectList fRects;
  256. typedef GM INHERITED;
  257. };
  258. DEF_GM(return new ConvexPolyEffect;)
  259. }