1cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett/* 2cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett * Copyright 2016 Google Inc. 3cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett * 4cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett * Use of this source code is governed by a BSD-style license that can be 5cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett * found in the LICENSE file. 6cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett */ 7cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 8fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon#include "GrRegionOp.h" 9f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon#include <GrDrawOpTest.h> 10dad2923b8ec9270d810c1e8e76da8e6768d8f9ddBrian Salomon#include "GrDefaultGeoProcFactory.h" 11dad2923b8ec9270d810c1e8e76da8e6768d8f9ddBrian Salomon#include "GrMeshDrawOp.h" 12742e31de1599f3902810aecdf2e2e3eed3b40a09Brian Salomon#include "GrOpFlushState.h" 13cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett#include "GrResourceProvider.h" 14f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon#include "GrSimpleMeshDrawOpHelper.h" 15cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett#include "SkMatrixPriv.h" 16cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett#include "SkRegion.h" 17cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 18cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarettstatic const int kVertsPerInstance = 4; 19cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarettstatic const int kIndicesPerInstance = 6; 20cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 218c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomonstatic sk_sp<GrGeometryProcessor> make_gp(const SkMatrix& viewMatrix) { 22cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett using namespace GrDefaultGeoProcFactory; 233de0aee181b8fe0013b15100cba7381eb0468db4Brian Salomon return GrDefaultGeoProcFactory::Make(Color::kPremulGrColorAttribute_Type, Coverage::kSolid_Type, 248c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon LocalCoords::kUsePosition_Type, viewMatrix); 25cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett} 26cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 27febb22469999b928850182ebc57bfd6fbd7402d6msarettstatic void tesselate_region(intptr_t vertices, 28fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon size_t vertexStride, 29fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon GrColor color, 30fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon const SkRegion& region) { 31cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett SkRegion::Iterator iter(region); 32cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 33cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett intptr_t verts = vertices; 34cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett while (!iter.done()) { 35febb22469999b928850182ebc57bfd6fbd7402d6msarett SkRect rect = SkRect::Make(iter.rect()); 36fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon SkPoint* position = (SkPoint*)verts; 37febb22469999b928850182ebc57bfd6fbd7402d6msarett position->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vertexStride); 38cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 39cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett static const int kColorOffset = sizeof(SkPoint); 40cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett GrColor* vertColor = reinterpret_cast<GrColor*>(verts + kColorOffset); 41cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett for (int i = 0; i < kVertsPerInstance; i++) { 42cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett *vertColor = color; 43fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon vertColor = (GrColor*)((intptr_t)vertColor + vertexStride); 44cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett } 45cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 46cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett verts += vertexStride * kVertsPerInstance; 47cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett iter.next(); 48cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett } 49cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett} 50cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 51f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomonnamespace { 52f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon 53f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomonclass RegionOp final : public GrMeshDrawOp { 54f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomonprivate: 55f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon using Helper = GrSimpleMeshDrawOpHelper; 56f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon 57cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarettpublic: 5825a880960a9a689a745a01071ecba3fe494b5940Brian Salomon DEFINE_OP_CLASS_ID 59cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 60f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon static std::unique_ptr<GrDrawOp> Make(GrPaint&& paint, const SkMatrix& viewMatrix, 61f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon const SkRegion& region, GrAAType aaType) { 62f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon return Helper::FactoryHelper<RegionOp>(std::move(paint), viewMatrix, region, aaType); 63f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon } 64f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon 65f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon RegionOp(const Helper::MakeArgs& helperArgs, GrColor color, const SkMatrix& viewMatrix, 66f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon const SkRegion& region, GrAAType aaType) 67f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon : INHERITED(ClassID()), fHelper(helperArgs, aaType), fViewMatrix(viewMatrix) { 68cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett RegionInfo& info = fRegions.push_back(); 69cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett info.fColor = color; 70cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett info.fRegion = region; 71cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 72cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett SkRect bounds = SkRect::Make(region.getBounds()); 73cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett this->setTransformedBounds(bounds, viewMatrix, HasAABloat::kNo, IsZeroArea::kNo); 74cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett } 75cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 76fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon const char* name() const override { return "GrRegionOp"; } 77cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 78cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett SkString dumpInfo() const override { 79cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett SkString str; 8053e4c3c0da40b58638d05e0f753ab6d450b961f5Brian Salomon str.appendf("# combined: %d\n", fRegions.count()); 81cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett for (int i = 0; i < fRegions.count(); ++i) { 82cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett const RegionInfo& info = fRegions[i]; 83fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon str.appendf("%d: Color: 0x%08x, Region with %d rects\n", i, info.fColor, 84fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon info.fRegion.computeRegionComplexity()); 85cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett } 86f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon str += fHelper.dumpInfo(); 87f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon str += INHERITED::dumpInfo(); 88cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett return str; 89cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett } 90cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 91f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon FixedFunctionFlags fixedFunctionFlags() const override { return fHelper.fixedFunctionFlags(); } 92cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 93f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon RequiresDstTexture finalize(const GrCaps& caps, const GrAppliedClip* clip) override { 94f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon return fHelper.xpRequiresDstTexture(caps, clip, GrProcessorAnalysisCoverage::kNone, 95f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon &fRegions[0].fColor); 96cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett } 97cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 98f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomonprivate: 99cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett void onPrepareDraws(Target* target) const override { 1008c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon sk_sp<GrGeometryProcessor> gp = make_gp(fViewMatrix); 101cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett if (!gp) { 102cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett SkDebugf("Couldn't create GrGeometryProcessor\n"); 103cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett return; 104cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett } 105febb22469999b928850182ebc57bfd6fbd7402d6msarett SkASSERT(gp->getVertexStride() == sizeof(GrDefaultGeoProcFactory::PositionColorAttr)); 106cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 107cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett int numRegions = fRegions.count(); 108cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett int numRects = 0; 109cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett for (int i = 0; i < numRegions; i++) { 110cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett numRects += fRegions[i].fRegion.computeRegionComplexity(); 111cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett } 112cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 113f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon if (!numRects) { 114f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon return; 115f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon } 116cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett size_t vertexStride = gp->getVertexStride(); 117144caf55ffc692bcda77703a73bb9a894f7d024fHal Canary sk_sp<const GrBuffer> indexBuffer(target->resourceProvider()->refQuadIndexBuffer()); 1183809bab7ed344ad140346c38e149dabf10bd525fChris Dalton PatternHelper helper(GrPrimitiveType::kTriangles); 119fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon void* vertices = 120bca46e29e9f96999df0b38fb9359e71b73217c94Chris Dalton helper.init(target, vertexStride, indexBuffer.get(), kVertsPerInstance, 121bca46e29e9f96999df0b38fb9359e71b73217c94Chris Dalton kIndicesPerInstance, numRects); 122cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett if (!vertices || !indexBuffer) { 123cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett SkDebugf("Could not allocate vertices\n"); 124cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett return; 125cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett } 126cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 127cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett intptr_t verts = reinterpret_cast<intptr_t>(vertices); 128cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett for (int i = 0; i < numRegions; i++) { 129febb22469999b928850182ebc57bfd6fbd7402d6msarett tesselate_region(verts, vertexStride, fRegions[i].fColor, fRegions[i].fRegion); 130febb22469999b928850182ebc57bfd6fbd7402d6msarett int numRectsInRegion = fRegions[i].fRegion.computeRegionComplexity(); 131cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett verts += numRectsInRegion * kVertsPerInstance * vertexStride; 132cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett } 133f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon helper.recordDraw(target, gp.get(), fHelper.makePipeline(target)); 134cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett } 135cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 13625a880960a9a689a745a01071ecba3fe494b5940Brian Salomon bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override { 137fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon RegionOp* that = t->cast<RegionOp>(); 138f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) { 139cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett return false; 140cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett } 141cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 142febb22469999b928850182ebc57bfd6fbd7402d6msarett if (fViewMatrix != that->fViewMatrix) { 143febb22469999b928850182ebc57bfd6fbd7402d6msarett return false; 144febb22469999b928850182ebc57bfd6fbd7402d6msarett } 145febb22469999b928850182ebc57bfd6fbd7402d6msarett 146cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett fRegions.push_back_n(that->fRegions.count(), that->fRegions.begin()); 147cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett this->joinBounds(*that); 148cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett return true; 149cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett } 150cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 151cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett struct RegionInfo { 152cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett GrColor fColor; 153cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett SkRegion fRegion; 154cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett }; 155cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 156f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon Helper fHelper; 157febb22469999b928850182ebc57bfd6fbd7402d6msarett SkMatrix fViewMatrix; 158cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett SkSTArray<1, RegionInfo, true> fRegions; 159cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 160f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon typedef GrMeshDrawOp INHERITED; 161cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett}; 162cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 163f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon} // anonymous namespace 164f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon 165fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomonnamespace GrRegionOp { 166cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 167f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomonstd::unique_ptr<GrDrawOp> Make(GrPaint&& paint, const SkMatrix& viewMatrix, const SkRegion& region, 168f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon GrAAType aaType) { 169f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon if (aaType != GrAAType::kNone && aaType != GrAAType::kMSAA) { 170f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon return nullptr; 171f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon } 172f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon return RegionOp::Make(std::move(paint), viewMatrix, region, aaType); 173fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon} 174cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett} 175f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon 176f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon#if GR_TEST_UTILS 177f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon 178f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian SalomonGR_DRAW_OP_TEST_DEFINE(RegionOp) { 179f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon SkRegion region; 180f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon int n = random->nextULessThan(200); 181f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon for (int i = 0; i < n; ++i) { 182f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon SkIPoint center; 183f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon center.fX = random->nextULessThan(1000); 184f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon center.fY = random->nextULessThan(1000); 185f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon int w = random->nextRangeU(10, 1000); 186f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon int h = random->nextRangeU(10, 1000); 187f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon SkIRect rect = {center.fX - w / 2, center.fY - h / 2, center.fX + w / 2, center.fY + h / 2}; 188f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon SkRegion::Op op; 189f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon if (i == 0) { 190f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon op = SkRegion::kReplace_Op; 191f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon } else { 192f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon // Pick an other than replace. 193f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon GR_STATIC_ASSERT(SkRegion::kLastOp == SkRegion::kReplace_Op); 194f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon op = (SkRegion::Op)random->nextULessThan(SkRegion::kLastOp); 195f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon } 196f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon region.op(rect, op); 197f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon } 198f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon SkMatrix viewMatrix = GrTest::TestMatrix(random); 199f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon GrAAType aaType = GrAAType::kNone; 200f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon if (GrFSAAType::kUnifiedMSAA == fsaaType && random->nextBool()) { 201f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon aaType = GrAAType::kMSAA; 202f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon } 203f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon return RegionOp::Make(std::move(paint), viewMatrix, region, aaType); 204f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon} 205f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon 206f0366326cc565c9e1535e4ac4baf273d7ea0d816Brian Salomon#endif 207