1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2016 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "src/gpu/ops/RegionOp.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "include/core/SkRegion.h" 11cb93a386Sopenharmony_ci#include "src/core/SkMatrixPriv.h" 12cb93a386Sopenharmony_ci#include "src/gpu/BufferWriter.h" 13cb93a386Sopenharmony_ci#include "src/gpu/GrCaps.h" 14cb93a386Sopenharmony_ci#include "src/gpu/GrDefaultGeoProcFactory.h" 15cb93a386Sopenharmony_ci#include "src/gpu/GrOpFlushState.h" 16cb93a386Sopenharmony_ci#include "src/gpu/GrProgramInfo.h" 17cb93a386Sopenharmony_ci#include "src/gpu/GrResourceProvider.h" 18cb93a386Sopenharmony_ci#include "src/gpu/ops/GrMeshDrawOp.h" 19cb93a386Sopenharmony_ci#include "src/gpu/ops/GrSimpleMeshDrawOpHelperWithStencil.h" 20cb93a386Sopenharmony_ci 21cb93a386Sopenharmony_cinamespace skgpu::v1::RegionOp { 22cb93a386Sopenharmony_ci 23cb93a386Sopenharmony_cinamespace { 24cb93a386Sopenharmony_ci 25cb93a386Sopenharmony_ciGrGeometryProcessor* make_gp(SkArenaAlloc* arena, 26cb93a386Sopenharmony_ci const SkMatrix& viewMatrix, 27cb93a386Sopenharmony_ci bool wideColor) { 28cb93a386Sopenharmony_ci using namespace GrDefaultGeoProcFactory; 29cb93a386Sopenharmony_ci Color::Type colorType = wideColor ? Color::kPremulWideColorAttribute_Type 30cb93a386Sopenharmony_ci : Color::kPremulGrColorAttribute_Type; 31cb93a386Sopenharmony_ci return GrDefaultGeoProcFactory::Make(arena, colorType, Coverage::kSolid_Type, 32cb93a386Sopenharmony_ci LocalCoords::kUsePosition_Type, viewMatrix); 33cb93a386Sopenharmony_ci} 34cb93a386Sopenharmony_ci 35cb93a386Sopenharmony_ciclass RegionOpImpl final : public GrMeshDrawOp { 36cb93a386Sopenharmony_ciprivate: 37cb93a386Sopenharmony_ci using Helper = GrSimpleMeshDrawOpHelperWithStencil; 38cb93a386Sopenharmony_ci 39cb93a386Sopenharmony_cipublic: 40cb93a386Sopenharmony_ci DEFINE_OP_CLASS_ID 41cb93a386Sopenharmony_ci 42cb93a386Sopenharmony_ci static GrOp::Owner Make(GrRecordingContext* context, 43cb93a386Sopenharmony_ci GrPaint&& paint, 44cb93a386Sopenharmony_ci const SkMatrix& viewMatrix, 45cb93a386Sopenharmony_ci const SkRegion& region, 46cb93a386Sopenharmony_ci GrAAType aaType, 47cb93a386Sopenharmony_ci const GrUserStencilSettings* stencilSettings = nullptr) { 48cb93a386Sopenharmony_ci return Helper::FactoryHelper<RegionOpImpl>(context, std::move(paint), viewMatrix, region, 49cb93a386Sopenharmony_ci aaType, stencilSettings); 50cb93a386Sopenharmony_ci } 51cb93a386Sopenharmony_ci 52cb93a386Sopenharmony_ci RegionOpImpl(GrProcessorSet* processorSet, const SkPMColor4f& color, 53cb93a386Sopenharmony_ci const SkMatrix& viewMatrix, const SkRegion& region, GrAAType aaType, 54cb93a386Sopenharmony_ci const GrUserStencilSettings* stencilSettings) 55cb93a386Sopenharmony_ci : INHERITED(ClassID()) 56cb93a386Sopenharmony_ci , fHelper(processorSet, aaType, stencilSettings) 57cb93a386Sopenharmony_ci , fViewMatrix(viewMatrix) { 58cb93a386Sopenharmony_ci RegionInfo& info = fRegions.push_back(); 59cb93a386Sopenharmony_ci info.fColor = color; 60cb93a386Sopenharmony_ci info.fRegion = region; 61cb93a386Sopenharmony_ci 62cb93a386Sopenharmony_ci SkRect bounds = SkRect::Make(region.getBounds()); 63cb93a386Sopenharmony_ci this->setTransformedBounds(bounds, viewMatrix, HasAABloat::kNo, IsHairline::kNo); 64cb93a386Sopenharmony_ci } 65cb93a386Sopenharmony_ci 66cb93a386Sopenharmony_ci const char* name() const override { return "GrRegionOp"; } 67cb93a386Sopenharmony_ci 68cb93a386Sopenharmony_ci void visitProxies(const GrVisitProxyFunc& func) const override { 69cb93a386Sopenharmony_ci if (fProgramInfo) { 70cb93a386Sopenharmony_ci fProgramInfo->visitFPProxies(func); 71cb93a386Sopenharmony_ci } else { 72cb93a386Sopenharmony_ci fHelper.visitProxies(func); 73cb93a386Sopenharmony_ci } 74cb93a386Sopenharmony_ci } 75cb93a386Sopenharmony_ci 76cb93a386Sopenharmony_ci FixedFunctionFlags fixedFunctionFlags() const override { return fHelper.fixedFunctionFlags(); } 77cb93a386Sopenharmony_ci 78cb93a386Sopenharmony_ci GrProcessorSet::Analysis finalize(const GrCaps& caps, const GrAppliedClip* clip, 79cb93a386Sopenharmony_ci GrClampType clampType) override { 80cb93a386Sopenharmony_ci return fHelper.finalizeProcessors(caps, clip, clampType, GrProcessorAnalysisCoverage::kNone, 81cb93a386Sopenharmony_ci &fRegions[0].fColor, &fWideColor); 82cb93a386Sopenharmony_ci } 83cb93a386Sopenharmony_ci 84cb93a386Sopenharmony_ciprivate: 85cb93a386Sopenharmony_ci GrProgramInfo* programInfo() override { return fProgramInfo; } 86cb93a386Sopenharmony_ci 87cb93a386Sopenharmony_ci void onCreateProgramInfo(const GrCaps* caps, 88cb93a386Sopenharmony_ci SkArenaAlloc* arena, 89cb93a386Sopenharmony_ci const GrSurfaceProxyView& writeView, 90cb93a386Sopenharmony_ci bool usesMSAASurface, 91cb93a386Sopenharmony_ci GrAppliedClip&& appliedClip, 92cb93a386Sopenharmony_ci const GrDstProxyView& dstProxyView, 93cb93a386Sopenharmony_ci GrXferBarrierFlags renderPassXferBarriers, 94cb93a386Sopenharmony_ci GrLoadOp colorLoadOp) override { 95cb93a386Sopenharmony_ci GrGeometryProcessor* gp = make_gp(arena, fViewMatrix, fWideColor); 96cb93a386Sopenharmony_ci if (!gp) { 97cb93a386Sopenharmony_ci SkDebugf("Couldn't create GrGeometryProcessor\n"); 98cb93a386Sopenharmony_ci return; 99cb93a386Sopenharmony_ci } 100cb93a386Sopenharmony_ci 101cb93a386Sopenharmony_ci fProgramInfo = fHelper.createProgramInfoWithStencil(caps, arena, writeView, usesMSAASurface, 102cb93a386Sopenharmony_ci std::move(appliedClip), dstProxyView, 103cb93a386Sopenharmony_ci gp, GrPrimitiveType::kTriangles, 104cb93a386Sopenharmony_ci renderPassXferBarriers, colorLoadOp); 105cb93a386Sopenharmony_ci } 106cb93a386Sopenharmony_ci 107cb93a386Sopenharmony_ci void onPrepareDraws(GrMeshDrawTarget* target) override { 108cb93a386Sopenharmony_ci if (!fProgramInfo) { 109cb93a386Sopenharmony_ci this->createProgramInfo(target); 110cb93a386Sopenharmony_ci if (!fProgramInfo) { 111cb93a386Sopenharmony_ci return; 112cb93a386Sopenharmony_ci } 113cb93a386Sopenharmony_ci } 114cb93a386Sopenharmony_ci 115cb93a386Sopenharmony_ci int numRegions = fRegions.count(); 116cb93a386Sopenharmony_ci int numRects = 0; 117cb93a386Sopenharmony_ci for (int i = 0; i < numRegions; i++) { 118cb93a386Sopenharmony_ci numRects += fRegions[i].fRegion.computeRegionComplexity(); 119cb93a386Sopenharmony_ci } 120cb93a386Sopenharmony_ci 121cb93a386Sopenharmony_ci if (!numRects) { 122cb93a386Sopenharmony_ci return; 123cb93a386Sopenharmony_ci } 124cb93a386Sopenharmony_ci 125cb93a386Sopenharmony_ci QuadHelper helper(target, fProgramInfo->geomProc().vertexStride(), numRects); 126cb93a386Sopenharmony_ci 127cb93a386Sopenharmony_ci VertexWriter vertices{helper.vertices()}; 128cb93a386Sopenharmony_ci if (!vertices) { 129cb93a386Sopenharmony_ci SkDebugf("Could not allocate vertices\n"); 130cb93a386Sopenharmony_ci return; 131cb93a386Sopenharmony_ci } 132cb93a386Sopenharmony_ci 133cb93a386Sopenharmony_ci for (int i = 0; i < numRegions; i++) { 134cb93a386Sopenharmony_ci GrVertexColor color(fRegions[i].fColor, fWideColor); 135cb93a386Sopenharmony_ci SkRegion::Iterator iter(fRegions[i].fRegion); 136cb93a386Sopenharmony_ci while (!iter.done()) { 137cb93a386Sopenharmony_ci SkRect rect = SkRect::Make(iter.rect()); 138cb93a386Sopenharmony_ci vertices.writeQuad(VertexWriter::TriStripFromRect(rect), color); 139cb93a386Sopenharmony_ci iter.next(); 140cb93a386Sopenharmony_ci } 141cb93a386Sopenharmony_ci } 142cb93a386Sopenharmony_ci 143cb93a386Sopenharmony_ci fMesh = helper.mesh(); 144cb93a386Sopenharmony_ci } 145cb93a386Sopenharmony_ci 146cb93a386Sopenharmony_ci void onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) override { 147cb93a386Sopenharmony_ci if (!fProgramInfo || !fMesh) { 148cb93a386Sopenharmony_ci return; 149cb93a386Sopenharmony_ci } 150cb93a386Sopenharmony_ci 151cb93a386Sopenharmony_ci flushState->bindPipelineAndScissorClip(*fProgramInfo, chainBounds); 152cb93a386Sopenharmony_ci flushState->bindTextures(fProgramInfo->geomProc(), nullptr, fProgramInfo->pipeline()); 153cb93a386Sopenharmony_ci flushState->drawMesh(*fMesh); 154cb93a386Sopenharmony_ci } 155cb93a386Sopenharmony_ci 156cb93a386Sopenharmony_ci CombineResult onCombineIfPossible(GrOp* t, SkArenaAlloc*, const GrCaps& caps) override { 157cb93a386Sopenharmony_ci auto that = t->cast<RegionOpImpl>(); 158cb93a386Sopenharmony_ci if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) { 159cb93a386Sopenharmony_ci return CombineResult::kCannotCombine; 160cb93a386Sopenharmony_ci } 161cb93a386Sopenharmony_ci 162cb93a386Sopenharmony_ci if (fViewMatrix != that->fViewMatrix) { 163cb93a386Sopenharmony_ci return CombineResult::kCannotCombine; 164cb93a386Sopenharmony_ci } 165cb93a386Sopenharmony_ci 166cb93a386Sopenharmony_ci fRegions.push_back_n(that->fRegions.count(), that->fRegions.begin()); 167cb93a386Sopenharmony_ci fWideColor |= that->fWideColor; 168cb93a386Sopenharmony_ci return CombineResult::kMerged; 169cb93a386Sopenharmony_ci } 170cb93a386Sopenharmony_ci 171cb93a386Sopenharmony_ci#if GR_TEST_UTILS 172cb93a386Sopenharmony_ci SkString onDumpInfo() const override { 173cb93a386Sopenharmony_ci SkString str = SkStringPrintf("# combined: %d\n", fRegions.count()); 174cb93a386Sopenharmony_ci for (int i = 0; i < fRegions.count(); ++i) { 175cb93a386Sopenharmony_ci const RegionInfo& info = fRegions[i]; 176cb93a386Sopenharmony_ci str.appendf("%d: Color: 0x%08x, Region with %d rects\n", i, info.fColor.toBytes_RGBA(), 177cb93a386Sopenharmony_ci info.fRegion.computeRegionComplexity()); 178cb93a386Sopenharmony_ci } 179cb93a386Sopenharmony_ci str += fHelper.dumpInfo(); 180cb93a386Sopenharmony_ci return str; 181cb93a386Sopenharmony_ci } 182cb93a386Sopenharmony_ci#endif 183cb93a386Sopenharmony_ci 184cb93a386Sopenharmony_ci struct RegionInfo { 185cb93a386Sopenharmony_ci SkPMColor4f fColor; 186cb93a386Sopenharmony_ci SkRegion fRegion; 187cb93a386Sopenharmony_ci }; 188cb93a386Sopenharmony_ci 189cb93a386Sopenharmony_ci Helper fHelper; 190cb93a386Sopenharmony_ci SkMatrix fViewMatrix; 191cb93a386Sopenharmony_ci SkSTArray<1, RegionInfo, true> fRegions; 192cb93a386Sopenharmony_ci bool fWideColor; 193cb93a386Sopenharmony_ci 194cb93a386Sopenharmony_ci GrSimpleMesh* fMesh = nullptr; 195cb93a386Sopenharmony_ci GrProgramInfo* fProgramInfo = nullptr; 196cb93a386Sopenharmony_ci 197cb93a386Sopenharmony_ci using INHERITED = GrMeshDrawOp; 198cb93a386Sopenharmony_ci}; 199cb93a386Sopenharmony_ci 200cb93a386Sopenharmony_ci} // anonymous namespace 201cb93a386Sopenharmony_ci 202cb93a386Sopenharmony_ciGrOp::Owner Make(GrRecordingContext* context, 203cb93a386Sopenharmony_ci GrPaint&& paint, 204cb93a386Sopenharmony_ci const SkMatrix& viewMatrix, 205cb93a386Sopenharmony_ci const SkRegion& region, 206cb93a386Sopenharmony_ci GrAAType aaType, 207cb93a386Sopenharmony_ci const GrUserStencilSettings* stencilSettings) { 208cb93a386Sopenharmony_ci if (aaType != GrAAType::kNone && aaType != GrAAType::kMSAA) { 209cb93a386Sopenharmony_ci return nullptr; 210cb93a386Sopenharmony_ci } 211cb93a386Sopenharmony_ci return RegionOpImpl::Make(context, std::move(paint), viewMatrix, region, aaType, 212cb93a386Sopenharmony_ci stencilSettings); 213cb93a386Sopenharmony_ci} 214cb93a386Sopenharmony_ci 215cb93a386Sopenharmony_ci} // namespace skgpu::v1::RegionOp 216cb93a386Sopenharmony_ci 217cb93a386Sopenharmony_ci#if GR_TEST_UTILS 218cb93a386Sopenharmony_ci 219cb93a386Sopenharmony_ci#include "src/gpu/GrDrawOpTest.h" 220cb93a386Sopenharmony_ci 221cb93a386Sopenharmony_ciGR_DRAW_OP_TEST_DEFINE(RegionOp) { 222cb93a386Sopenharmony_ci SkRegion region; 223cb93a386Sopenharmony_ci int n = random->nextULessThan(200); 224cb93a386Sopenharmony_ci for (int i = 0; i < n; ++i) { 225cb93a386Sopenharmony_ci SkIPoint center; 226cb93a386Sopenharmony_ci center.fX = random->nextULessThan(1000); 227cb93a386Sopenharmony_ci center.fY = random->nextULessThan(1000); 228cb93a386Sopenharmony_ci int w = random->nextRangeU(10, 1000); 229cb93a386Sopenharmony_ci int h = random->nextRangeU(10, 1000); 230cb93a386Sopenharmony_ci SkIRect rect = {center.fX - w / 2, center.fY - h / 2, center.fX + w / 2, center.fY + h / 2}; 231cb93a386Sopenharmony_ci SkRegion::Op op; 232cb93a386Sopenharmony_ci if (i == 0) { 233cb93a386Sopenharmony_ci op = SkRegion::kReplace_Op; 234cb93a386Sopenharmony_ci } else { 235cb93a386Sopenharmony_ci // Pick an other than replace. 236cb93a386Sopenharmony_ci static_assert(SkRegion::kLastOp == SkRegion::kReplace_Op); 237cb93a386Sopenharmony_ci op = (SkRegion::Op)random->nextULessThan(SkRegion::kLastOp); 238cb93a386Sopenharmony_ci } 239cb93a386Sopenharmony_ci region.op(rect, op); 240cb93a386Sopenharmony_ci } 241cb93a386Sopenharmony_ci SkMatrix viewMatrix = GrTest::TestMatrix(random); 242cb93a386Sopenharmony_ci GrAAType aaType = GrAAType::kNone; 243cb93a386Sopenharmony_ci if (numSamples > 1 && random->nextBool()) { 244cb93a386Sopenharmony_ci aaType = GrAAType::kMSAA; 245cb93a386Sopenharmony_ci } 246cb93a386Sopenharmony_ci return skgpu::v1::RegionOp::RegionOpImpl::Make(context, std::move(paint), viewMatrix, region, 247cb93a386Sopenharmony_ci aaType, GrGetRandomStencil(random, context)); 248cb93a386Sopenharmony_ci} 249cb93a386Sopenharmony_ci 250cb93a386Sopenharmony_ci#endif // GR_TEST_UTILS 251