blob: ae09a5f290779a0735376c84860f80d6575a0482 [file] [log] [blame]
msarettcc319b92016-08-25 18:07:18 -07001/*
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 "GrRegionBatch.h"
9
10#include "GrDefaultGeoProcFactory.h"
11#include "GrBatchFlushState.h"
12#include "GrResourceProvider.h"
13#include "GrVertexBatch.h"
14#include "SkMatrixPriv.h"
15#include "SkRegion.h"
16
17static const int kVertsPerInstance = 4;
18static const int kIndicesPerInstance = 6;
19
msarettfebb2242016-08-26 12:49:27 -070020static sk_sp<GrGeometryProcessor> make_gp(bool readsCoverage, const SkMatrix& viewMatrix) {
msarettcc319b92016-08-25 18:07:18 -070021 using namespace GrDefaultGeoProcFactory;
22 Color color(Color::kAttribute_Type);
23 Coverage coverage(readsCoverage ? Coverage::kSolid_Type : Coverage::kNone_Type);
24
msarettfebb2242016-08-26 12:49:27 -070025 LocalCoords localCoords(LocalCoords::kUsePosition_Type);
26 return GrDefaultGeoProcFactory::Make(color, coverage, localCoords, viewMatrix);
msarettcc319b92016-08-25 18:07:18 -070027}
28
msarettfebb2242016-08-26 12:49:27 -070029static void tesselate_region(intptr_t vertices,
msarettcc319b92016-08-25 18:07:18 -070030 size_t vertexStride,
31 GrColor color,
msarettcc319b92016-08-25 18:07:18 -070032 const SkRegion& region) {
33 SkRegion::Iterator iter(region);
34
35 intptr_t verts = vertices;
36 while (!iter.done()) {
msarettfebb2242016-08-26 12:49:27 -070037 SkRect rect = SkRect::Make(iter.rect());
msarettcc319b92016-08-25 18:07:18 -070038 SkPoint* position = (SkPoint*) verts;
msarettfebb2242016-08-26 12:49:27 -070039 position->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vertexStride);
msarettcc319b92016-08-25 18:07:18 -070040
41 static const int kColorOffset = sizeof(SkPoint);
42 GrColor* vertColor = reinterpret_cast<GrColor*>(verts + kColorOffset);
43 for (int i = 0; i < kVertsPerInstance; i++) {
44 *vertColor = color;
45 vertColor = (GrColor*) ((intptr_t) vertColor + vertexStride);
46 }
47
48 verts += vertexStride * kVertsPerInstance;
49 iter.next();
50 }
msarettcc319b92016-08-25 18:07:18 -070051}
52
53class RegionBatch : public GrVertexBatch {
54public:
55 DEFINE_BATCH_CLASS_ID
56
57 RegionBatch(GrColor color, const SkMatrix& viewMatrix, const SkRegion& region)
msarettfebb2242016-08-26 12:49:27 -070058 : INHERITED(ClassID())
59 , fViewMatrix(viewMatrix)
60 {
msarettcc319b92016-08-25 18:07:18 -070061 RegionInfo& info = fRegions.push_back();
62 info.fColor = color;
msarettcc319b92016-08-25 18:07:18 -070063 info.fRegion = region;
64
65 SkRect bounds = SkRect::Make(region.getBounds());
66 this->setTransformedBounds(bounds, viewMatrix, HasAABloat::kNo, IsZeroArea::kNo);
67 }
68
69 const char* name() const override { return "GrRegionBatch"; }
70
71 SkString dumpInfo() const override {
72 SkString str;
73 str.appendf("# batched: %d\n", fRegions.count());
74 for (int i = 0; i < fRegions.count(); ++i) {
75 const RegionInfo& info = fRegions[i];
76 str.appendf("%d: Color: 0x%08x, Region with %d rects\n",
77 i, info.fColor, info.fRegion.computeRegionComplexity());
78 }
Brian Salomon7c3e7182016-12-01 09:35:30 -050079 str.append(DumpPipelineInfo(*this->pipeline()));
msarettcc319b92016-08-25 18:07:18 -070080 str.append(INHERITED::dumpInfo());
81 return str;
82 }
83
84 void computePipelineOptimizations(GrInitInvariantOutput* color,
85 GrInitInvariantOutput* coverage,
86 GrBatchToXPOverrides* overrides) const override {
87 // When this is called on a batch, there is only one region.
88 color->setKnownFourComponents(fRegions[0].fColor);
89 coverage->setKnownSingleComponent(0xff);
90 }
91
92 void initBatchTracker(const GrXPOverridesForBatch& overrides) override {
93 overrides.getOverrideColorIfSet(&fRegions[0].fColor);
94 fOverrides = overrides;
95 }
96
97private:
98
99 void onPrepareDraws(Target* target) const override {
msarettfebb2242016-08-26 12:49:27 -0700100 sk_sp<GrGeometryProcessor> gp = make_gp(fOverrides.readsCoverage(), fViewMatrix);
msarettcc319b92016-08-25 18:07:18 -0700101 if (!gp) {
102 SkDebugf("Couldn't create GrGeometryProcessor\n");
103 return;
104 }
msarettfebb2242016-08-26 12:49:27 -0700105 SkASSERT(gp->getVertexStride() == sizeof(GrDefaultGeoProcFactory::PositionColorAttr));
msarettcc319b92016-08-25 18:07:18 -0700106
107 int numRegions = fRegions.count();
108 int numRects = 0;
109 for (int i = 0; i < numRegions; i++) {
110 numRects += fRegions[i].fRegion.computeRegionComplexity();
111 }
112
113 size_t vertexStride = gp->getVertexStride();
Hal Canary144caf52016-11-07 17:57:18 -0500114 sk_sp<const GrBuffer> indexBuffer(target->resourceProvider()->refQuadIndexBuffer());
msarettcc319b92016-08-25 18:07:18 -0700115 InstancedHelper helper;
116 void* vertices = helper.init(target, kTriangles_GrPrimitiveType, vertexStride,
Hal Canary144caf52016-11-07 17:57:18 -0500117 indexBuffer.get(), kVertsPerInstance, kIndicesPerInstance,
118 numRects);
msarettcc319b92016-08-25 18:07:18 -0700119 if (!vertices || !indexBuffer) {
120 SkDebugf("Could not allocate vertices\n");
121 return;
122 }
123
124 intptr_t verts = reinterpret_cast<intptr_t>(vertices);
125 for (int i = 0; i < numRegions; i++) {
msarettfebb2242016-08-26 12:49:27 -0700126 tesselate_region(verts, vertexStride, fRegions[i].fColor, fRegions[i].fRegion);
127 int numRectsInRegion = fRegions[i].fRegion.computeRegionComplexity();
msarettcc319b92016-08-25 18:07:18 -0700128 verts += numRectsInRegion * kVertsPerInstance * vertexStride;
129 }
130 helper.recordDraw(target, gp.get());
131 }
132
133 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override {
134 RegionBatch* that = t->cast<RegionBatch>();
135 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
136 that->bounds(), caps)) {
137 return false;
138 }
139
msarettfebb2242016-08-26 12:49:27 -0700140 if (fViewMatrix != that->fViewMatrix) {
141 return false;
142 }
143
msarettcc319b92016-08-25 18:07:18 -0700144 fRegions.push_back_n(that->fRegions.count(), that->fRegions.begin());
145 this->joinBounds(*that);
146 return true;
147 }
148
149 struct RegionInfo {
150 GrColor fColor;
msarettcc319b92016-08-25 18:07:18 -0700151 SkRegion fRegion;
152 };
153
msarettfebb2242016-08-26 12:49:27 -0700154 SkMatrix fViewMatrix;
msarettcc319b92016-08-25 18:07:18 -0700155 GrXPOverridesForBatch fOverrides;
156 SkSTArray<1, RegionInfo, true> fRegions;
157
158 typedef GrVertexBatch INHERITED;
159};
160
161namespace GrRegionBatch {
162
163GrDrawBatch* Create(GrColor color,
164 const SkMatrix& viewMatrix,
165 const SkRegion& region) {
166 return new RegionBatch(color, viewMatrix, region);
167}
168
169};