• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "GrRegionOp.h"
9 
10 #include "GrDefaultGeoProcFactory.h"
11 #include "GrMeshDrawOp.h"
12 #include "GrOpFlushState.h"
13 #include "GrResourceProvider.h"
14 #include "SkMatrixPriv.h"
15 #include "SkRegion.h"
16 
17 static const int kVertsPerInstance = 4;
18 static const int kIndicesPerInstance = 6;
19 
make_gp(const SkMatrix & viewMatrix)20 static sk_sp<GrGeometryProcessor> make_gp(const SkMatrix& viewMatrix) {
21     using namespace GrDefaultGeoProcFactory;
22     return GrDefaultGeoProcFactory::Make(Color::kPremulGrColorAttribute_Type, Coverage::kSolid_Type,
23                                          LocalCoords::kUsePosition_Type, viewMatrix);
24 }
25 
tesselate_region(intptr_t vertices,size_t vertexStride,GrColor color,const SkRegion & region)26 static void tesselate_region(intptr_t vertices,
27                              size_t vertexStride,
28                              GrColor color,
29                              const SkRegion& region) {
30     SkRegion::Iterator iter(region);
31 
32     intptr_t verts = vertices;
33     while (!iter.done()) {
34         SkRect rect = SkRect::Make(iter.rect());
35         SkPoint* position = (SkPoint*)verts;
36         position->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vertexStride);
37 
38         static const int kColorOffset = sizeof(SkPoint);
39         GrColor* vertColor = reinterpret_cast<GrColor*>(verts + kColorOffset);
40         for (int i = 0; i < kVertsPerInstance; i++) {
41             *vertColor = color;
42             vertColor = (GrColor*)((intptr_t)vertColor + vertexStride);
43         }
44 
45         verts += vertexStride * kVertsPerInstance;
46         iter.next();
47     }
48 }
49 
50 class RegionOp final : public GrMeshDrawOp {
51 public:
52     DEFINE_OP_CLASS_ID
53 
RegionOp(GrColor color,const SkMatrix & viewMatrix,const SkRegion & region)54     RegionOp(GrColor color, const SkMatrix& viewMatrix, const SkRegion& region)
55             : INHERITED(ClassID()), fViewMatrix(viewMatrix) {
56         RegionInfo& info = fRegions.push_back();
57         info.fColor = color;
58         info.fRegion = region;
59 
60         SkRect bounds = SkRect::Make(region.getBounds());
61         this->setTransformedBounds(bounds, viewMatrix, HasAABloat::kNo, IsZeroArea::kNo);
62     }
63 
name() const64     const char* name() const override { return "GrRegionOp"; }
65 
dumpInfo() const66     SkString dumpInfo() const override {
67         SkString str;
68         str.appendf("# combined: %d\n", fRegions.count());
69         for (int i = 0; i < fRegions.count(); ++i) {
70             const RegionInfo& info = fRegions[i];
71             str.appendf("%d: Color: 0x%08x, Region with %d rects\n", i, info.fColor,
72                         info.fRegion.computeRegionComplexity());
73         }
74         str.append(DumpPipelineInfo(*this->pipeline()));
75         str.append(INHERITED::dumpInfo());
76         return str;
77     }
78 
79 private:
getFragmentProcessorAnalysisInputs(GrPipelineAnalysisColor * color,GrPipelineAnalysisCoverage * coverage) const80     void getFragmentProcessorAnalysisInputs(GrPipelineAnalysisColor* color,
81                                             GrPipelineAnalysisCoverage* coverage) const override {
82         color->setToConstant(fRegions[0].fColor);
83         *coverage = GrPipelineAnalysisCoverage::kNone;
84     }
85 
applyPipelineOptimizations(const GrPipelineOptimizations & optimizations)86     void applyPipelineOptimizations(const GrPipelineOptimizations& optimizations) override {
87         optimizations.getOverrideColorIfSet(&fRegions[0].fColor);
88     }
89 
onPrepareDraws(Target * target) const90     void onPrepareDraws(Target* target) const override {
91         sk_sp<GrGeometryProcessor> gp = make_gp(fViewMatrix);
92         if (!gp) {
93             SkDebugf("Couldn't create GrGeometryProcessor\n");
94             return;
95         }
96         SkASSERT(gp->getVertexStride() == sizeof(GrDefaultGeoProcFactory::PositionColorAttr));
97 
98         int numRegions = fRegions.count();
99         int numRects = 0;
100         for (int i = 0; i < numRegions; i++) {
101             numRects += fRegions[i].fRegion.computeRegionComplexity();
102         }
103 
104         size_t vertexStride = gp->getVertexStride();
105         sk_sp<const GrBuffer> indexBuffer(target->resourceProvider()->refQuadIndexBuffer());
106         InstancedHelper helper;
107         void* vertices =
108                 helper.init(target, kTriangles_GrPrimitiveType, vertexStride, indexBuffer.get(),
109                             kVertsPerInstance, kIndicesPerInstance, numRects);
110         if (!vertices || !indexBuffer) {
111             SkDebugf("Could not allocate vertices\n");
112             return;
113         }
114 
115         intptr_t verts = reinterpret_cast<intptr_t>(vertices);
116         for (int i = 0; i < numRegions; i++) {
117             tesselate_region(verts, vertexStride, fRegions[i].fColor, fRegions[i].fRegion);
118             int numRectsInRegion = fRegions[i].fRegion.computeRegionComplexity();
119             verts += numRectsInRegion * kVertsPerInstance * vertexStride;
120         }
121         helper.recordDraw(target, gp.get());
122     }
123 
onCombineIfPossible(GrOp * t,const GrCaps & caps)124     bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
125         RegionOp* that = t->cast<RegionOp>();
126         if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
127                                     that->bounds(), caps)) {
128             return false;
129         }
130 
131         if (fViewMatrix != that->fViewMatrix) {
132             return false;
133         }
134 
135         fRegions.push_back_n(that->fRegions.count(), that->fRegions.begin());
136         this->joinBounds(*that);
137         return true;
138     }
139 
140     struct RegionInfo {
141         GrColor fColor;
142         SkRegion fRegion;
143     };
144 
145     SkMatrix fViewMatrix;
146     SkSTArray<1, RegionInfo, true> fRegions;
147 
148     typedef GrMeshDrawOp INHERITED;
149 };
150 
151 namespace GrRegionOp {
152 
Make(GrColor color,const SkMatrix & viewMatrix,const SkRegion & region)153 std::unique_ptr<GrMeshDrawOp> Make(GrColor color, const SkMatrix& viewMatrix,
154                                    const SkRegion& region) {
155     return std::unique_ptr<GrMeshDrawOp>(new RegionOp(color, viewMatrix, region));
156 }
157 }
158