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