GrRegionOp.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. /*
  2. * Copyright 2016 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/GrRegionOp.h"
  8. #include "include/core/SkRegion.h"
  9. #include "src/core/SkMatrixPriv.h"
  10. #include "src/gpu/GrCaps.h"
  11. #include "src/gpu/GrDefaultGeoProcFactory.h"
  12. #include "src/gpu/GrDrawOpTest.h"
  13. #include "src/gpu/GrOpFlushState.h"
  14. #include "src/gpu/GrResourceProvider.h"
  15. #include "src/gpu/GrVertexWriter.h"
  16. #include "src/gpu/ops/GrMeshDrawOp.h"
  17. #include "src/gpu/ops/GrSimpleMeshDrawOpHelper.h"
  18. static const int kVertsPerInstance = 4;
  19. static const int kIndicesPerInstance = 6;
  20. static sk_sp<GrGeometryProcessor> make_gp(const GrShaderCaps* shaderCaps,
  21. const SkMatrix& viewMatrix,
  22. bool wideColor) {
  23. using namespace GrDefaultGeoProcFactory;
  24. Color::Type colorType =
  25. wideColor ? Color::kPremulWideColorAttribute_Type : Color::kPremulGrColorAttribute_Type;
  26. return GrDefaultGeoProcFactory::Make(shaderCaps, colorType, Coverage::kSolid_Type,
  27. LocalCoords::kUsePosition_Type, viewMatrix);
  28. }
  29. namespace {
  30. class RegionOp final : public GrMeshDrawOp {
  31. private:
  32. using Helper = GrSimpleMeshDrawOpHelperWithStencil;
  33. public:
  34. DEFINE_OP_CLASS_ID
  35. static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
  36. GrPaint&& paint,
  37. const SkMatrix& viewMatrix,
  38. const SkRegion& region,
  39. GrAAType aaType,
  40. const GrUserStencilSettings* stencilSettings = nullptr) {
  41. return Helper::FactoryHelper<RegionOp>(context, std::move(paint), viewMatrix, region,
  42. aaType, stencilSettings);
  43. }
  44. RegionOp(const Helper::MakeArgs& helperArgs, const SkPMColor4f& color,
  45. const SkMatrix& viewMatrix, const SkRegion& region, GrAAType aaType,
  46. const GrUserStencilSettings* stencilSettings)
  47. : INHERITED(ClassID())
  48. , fHelper(helperArgs, aaType, stencilSettings)
  49. , fViewMatrix(viewMatrix) {
  50. RegionInfo& info = fRegions.push_back();
  51. info.fColor = color;
  52. info.fRegion = region;
  53. SkRect bounds = SkRect::Make(region.getBounds());
  54. this->setTransformedBounds(bounds, viewMatrix, HasAABloat::kNo, IsZeroArea::kNo);
  55. }
  56. const char* name() const override { return "GrRegionOp"; }
  57. void visitProxies(const VisitProxyFunc& func) const override {
  58. fHelper.visitProxies(func);
  59. }
  60. #ifdef SK_DEBUG
  61. SkString dumpInfo() const override {
  62. SkString str;
  63. str.appendf("# combined: %d\n", fRegions.count());
  64. for (int i = 0; i < fRegions.count(); ++i) {
  65. const RegionInfo& info = fRegions[i];
  66. str.appendf("%d: Color: 0x%08x, Region with %d rects\n", i, info.fColor.toBytes_RGBA(),
  67. info.fRegion.computeRegionComplexity());
  68. }
  69. str += fHelper.dumpInfo();
  70. str += INHERITED::dumpInfo();
  71. return str;
  72. }
  73. #endif
  74. FixedFunctionFlags fixedFunctionFlags() const override { return fHelper.fixedFunctionFlags(); }
  75. GrProcessorSet::Analysis finalize(
  76. const GrCaps& caps, const GrAppliedClip* clip, bool hasMixedSampledCoverage,
  77. GrClampType clampType) override {
  78. return fHelper.finalizeProcessors(
  79. caps, clip, hasMixedSampledCoverage, clampType, GrProcessorAnalysisCoverage::kNone,
  80. &fRegions[0].fColor, &fWideColor);
  81. }
  82. private:
  83. void onPrepareDraws(Target* target) override {
  84. sk_sp<GrGeometryProcessor> gp = make_gp(target->caps().shaderCaps(), fViewMatrix,
  85. fWideColor);
  86. if (!gp) {
  87. SkDebugf("Couldn't create GrGeometryProcessor\n");
  88. return;
  89. }
  90. int numRegions = fRegions.count();
  91. int numRects = 0;
  92. for (int i = 0; i < numRegions; i++) {
  93. numRects += fRegions[i].fRegion.computeRegionComplexity();
  94. }
  95. if (!numRects) {
  96. return;
  97. }
  98. sk_sp<const GrGpuBuffer> indexBuffer = target->resourceProvider()->refQuadIndexBuffer();
  99. if (!indexBuffer) {
  100. SkDebugf("Could not allocate indices\n");
  101. return;
  102. }
  103. PatternHelper helper(target, GrPrimitiveType::kTriangles, gp->vertexStride(),
  104. std::move(indexBuffer), kVertsPerInstance, kIndicesPerInstance,
  105. numRects);
  106. GrVertexWriter vertices{helper.vertices()};
  107. if (!vertices.fPtr) {
  108. SkDebugf("Could not allocate vertices\n");
  109. return;
  110. }
  111. for (int i = 0; i < numRegions; i++) {
  112. GrVertexColor color(fRegions[i].fColor, fWideColor);
  113. SkRegion::Iterator iter(fRegions[i].fRegion);
  114. while (!iter.done()) {
  115. SkRect rect = SkRect::Make(iter.rect());
  116. vertices.writeQuad(GrVertexWriter::TriStripFromRect(rect), color);
  117. iter.next();
  118. }
  119. }
  120. helper.recordDraw(target, std::move(gp));
  121. }
  122. void onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) override {
  123. fHelper.executeDrawsAndUploads(this, flushState, chainBounds);
  124. }
  125. CombineResult onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
  126. RegionOp* that = t->cast<RegionOp>();
  127. if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) {
  128. return CombineResult::kCannotCombine;
  129. }
  130. if (fViewMatrix != that->fViewMatrix) {
  131. return CombineResult::kCannotCombine;
  132. }
  133. fRegions.push_back_n(that->fRegions.count(), that->fRegions.begin());
  134. fWideColor |= that->fWideColor;
  135. return CombineResult::kMerged;
  136. }
  137. struct RegionInfo {
  138. SkPMColor4f fColor;
  139. SkRegion fRegion;
  140. };
  141. Helper fHelper;
  142. SkMatrix fViewMatrix;
  143. SkSTArray<1, RegionInfo, true> fRegions;
  144. bool fWideColor;
  145. typedef GrMeshDrawOp INHERITED;
  146. };
  147. } // anonymous namespace
  148. namespace GrRegionOp {
  149. std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
  150. GrPaint&& paint,
  151. const SkMatrix& viewMatrix,
  152. const SkRegion& region,
  153. GrAAType aaType,
  154. const GrUserStencilSettings* stencilSettings) {
  155. if (aaType != GrAAType::kNone && aaType != GrAAType::kMSAA) {
  156. return nullptr;
  157. }
  158. return RegionOp::Make(context, std::move(paint), viewMatrix, region, aaType, stencilSettings);
  159. }
  160. }
  161. #if GR_TEST_UTILS
  162. GR_DRAW_OP_TEST_DEFINE(RegionOp) {
  163. SkRegion region;
  164. int n = random->nextULessThan(200);
  165. for (int i = 0; i < n; ++i) {
  166. SkIPoint center;
  167. center.fX = random->nextULessThan(1000);
  168. center.fY = random->nextULessThan(1000);
  169. int w = random->nextRangeU(10, 1000);
  170. int h = random->nextRangeU(10, 1000);
  171. SkIRect rect = {center.fX - w / 2, center.fY - h / 2, center.fX + w / 2, center.fY + h / 2};
  172. SkRegion::Op op;
  173. if (i == 0) {
  174. op = SkRegion::kReplace_Op;
  175. } else {
  176. // Pick an other than replace.
  177. GR_STATIC_ASSERT(SkRegion::kLastOp == SkRegion::kReplace_Op);
  178. op = (SkRegion::Op)random->nextULessThan(SkRegion::kLastOp);
  179. }
  180. region.op(rect, op);
  181. }
  182. SkMatrix viewMatrix = GrTest::TestMatrix(random);
  183. GrAAType aaType = GrAAType::kNone;
  184. if (numSamples > 1 && random->nextBool()) {
  185. aaType = GrAAType::kMSAA;
  186. }
  187. return RegionOp::Make(context, std::move(paint), viewMatrix, region, aaType,
  188. GrGetRandomStencil(random, context));
  189. }
  190. #endif