blob: 62d736263568b250c807b3405f828e44fe15fad0 [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
Brian Salomonfc527d22016-12-14 21:07:01 -05008#include "GrRegionOp.h"
msarettcc319b92016-08-25 18:07:18 -07009
Brian Salomondad29232016-12-01 16:40:24 -050010#include "GrDefaultGeoProcFactory.h"
11#include "GrMeshDrawOp.h"
Brian Salomon742e31d2016-12-07 17:06:19 -050012#include "GrOpFlushState.h"
msarettcc319b92016-08-25 18:07:18 -070013#include "GrResourceProvider.h"
msarettcc319b92016-08-25 18:07:18 -070014#include "SkMatrixPriv.h"
15#include "SkRegion.h"
16
17static const int kVertsPerInstance = 4;
18static const int kIndicesPerInstance = 6;
19
Brian Salomon8c852be2017-01-04 10:44:42 -050020static sk_sp<GrGeometryProcessor> make_gp(const SkMatrix& viewMatrix) {
msarettcc319b92016-08-25 18:07:18 -070021 using namespace GrDefaultGeoProcFactory;
Brian Salomon3de0aee2017-01-29 09:34:17 -050022 return GrDefaultGeoProcFactory::Make(Color::kPremulGrColorAttribute_Type, Coverage::kSolid_Type,
Brian Salomon8c852be2017-01-04 10:44:42 -050023 LocalCoords::kUsePosition_Type, viewMatrix);
msarettcc319b92016-08-25 18:07:18 -070024}
25
msarettfebb2242016-08-26 12:49:27 -070026static void tesselate_region(intptr_t vertices,
Brian Salomonfc527d22016-12-14 21:07:01 -050027 size_t vertexStride,
28 GrColor color,
29 const SkRegion& region) {
msarettcc319b92016-08-25 18:07:18 -070030 SkRegion::Iterator iter(region);
31
32 intptr_t verts = vertices;
33 while (!iter.done()) {
msarettfebb2242016-08-26 12:49:27 -070034 SkRect rect = SkRect::Make(iter.rect());
Brian Salomonfc527d22016-12-14 21:07:01 -050035 SkPoint* position = (SkPoint*)verts;
msarettfebb2242016-08-26 12:49:27 -070036 position->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vertexStride);
msarettcc319b92016-08-25 18:07:18 -070037
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;
Brian Salomonfc527d22016-12-14 21:07:01 -050042 vertColor = (GrColor*)((intptr_t)vertColor + vertexStride);
msarettcc319b92016-08-25 18:07:18 -070043 }
44
45 verts += vertexStride * kVertsPerInstance;
46 iter.next();
47 }
msarettcc319b92016-08-25 18:07:18 -070048}
49
Brian Salomond3ccb0a2017-04-03 10:38:00 -040050class RegionOp final : public GrLegacyMeshDrawOp {
msarettcc319b92016-08-25 18:07:18 -070051public:
Brian Salomon25a88092016-12-01 09:36:50 -050052 DEFINE_OP_CLASS_ID
msarettcc319b92016-08-25 18:07:18 -070053
Brian Salomonfc527d22016-12-14 21:07:01 -050054 RegionOp(GrColor color, const SkMatrix& viewMatrix, const SkRegion& region)
55 : INHERITED(ClassID()), fViewMatrix(viewMatrix) {
msarettcc319b92016-08-25 18:07:18 -070056 RegionInfo& info = fRegions.push_back();
57 info.fColor = color;
msarettcc319b92016-08-25 18:07:18 -070058 info.fRegion = region;
59
60 SkRect bounds = SkRect::Make(region.getBounds());
61 this->setTransformedBounds(bounds, viewMatrix, HasAABloat::kNo, IsZeroArea::kNo);
62 }
63
Brian Salomonfc527d22016-12-14 21:07:01 -050064 const char* name() const override { return "GrRegionOp"; }
msarettcc319b92016-08-25 18:07:18 -070065
66 SkString dumpInfo() const override {
67 SkString str;
Brian Salomon53e4c3c2016-12-21 11:38:53 -050068 str.appendf("# combined: %d\n", fRegions.count());
msarettcc319b92016-08-25 18:07:18 -070069 for (int i = 0; i < fRegions.count(); ++i) {
70 const RegionInfo& info = fRegions[i];
Brian Salomonfc527d22016-12-14 21:07:01 -050071 str.appendf("%d: Color: 0x%08x, Region with %d rects\n", i, info.fColor,
72 info.fRegion.computeRegionComplexity());
msarettcc319b92016-08-25 18:07:18 -070073 }
Brian Salomon7c3e7182016-12-01 09:35:30 -050074 str.append(DumpPipelineInfo(*this->pipeline()));
msarettcc319b92016-08-25 18:07:18 -070075 str.append(INHERITED::dumpInfo());
76 return str;
77 }
78
msarettcc319b92016-08-25 18:07:18 -070079private:
Brian Salomona811b122017-03-30 08:21:32 -040080 void getProcessorAnalysisInputs(GrProcessorAnalysisColor* color,
81 GrProcessorAnalysisCoverage* coverage) const override {
Brian Salomonc0b642c2017-03-27 13:09:36 -040082 color->setToConstant(fRegions[0].fColor);
Brian Salomona811b122017-03-30 08:21:32 -040083 *coverage = GrProcessorAnalysisCoverage::kNone;
Brian Salomon92aee3d2016-12-21 09:20:25 -050084 }
85
Brian Salomone7d30482017-03-29 12:09:15 -040086 void applyPipelineOptimizations(const PipelineOptimizations& optimizations) override {
Brian Salomon92aee3d2016-12-21 09:20:25 -050087 optimizations.getOverrideColorIfSet(&fRegions[0].fColor);
Brian Salomon92aee3d2016-12-21 09:20:25 -050088 }
89
msarettcc319b92016-08-25 18:07:18 -070090 void onPrepareDraws(Target* target) const override {
Brian Salomon8c852be2017-01-04 10:44:42 -050091 sk_sp<GrGeometryProcessor> gp = make_gp(fViewMatrix);
msarettcc319b92016-08-25 18:07:18 -070092 if (!gp) {
93 SkDebugf("Couldn't create GrGeometryProcessor\n");
94 return;
95 }
msarettfebb2242016-08-26 12:49:27 -070096 SkASSERT(gp->getVertexStride() == sizeof(GrDefaultGeoProcFactory::PositionColorAttr));
msarettcc319b92016-08-25 18:07:18 -070097
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();
Hal Canary144caf52016-11-07 17:57:18 -0500105 sk_sp<const GrBuffer> indexBuffer(target->resourceProvider()->refQuadIndexBuffer());
Chris Daltonbca46e22017-05-15 11:03:26 -0600106 PatternHelper helper(kTriangles_GrPrimitiveType);
Brian Salomonfc527d22016-12-14 21:07:01 -0500107 void* vertices =
Chris Daltonbca46e22017-05-15 11:03:26 -0600108 helper.init(target, vertexStride, indexBuffer.get(), kVertsPerInstance,
109 kIndicesPerInstance, numRects);
msarettcc319b92016-08-25 18:07:18 -0700110 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++) {
msarettfebb2242016-08-26 12:49:27 -0700117 tesselate_region(verts, vertexStride, fRegions[i].fColor, fRegions[i].fRegion);
118 int numRectsInRegion = fRegions[i].fRegion.computeRegionComplexity();
msarettcc319b92016-08-25 18:07:18 -0700119 verts += numRectsInRegion * kVertsPerInstance * vertexStride;
120 }
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400121 helper.recordDraw(target, gp.get(), this->pipeline());
msarettcc319b92016-08-25 18:07:18 -0700122 }
123
Brian Salomon25a88092016-12-01 09:36:50 -0500124 bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
Brian Salomonfc527d22016-12-14 21:07:01 -0500125 RegionOp* that = t->cast<RegionOp>();
msarettcc319b92016-08-25 18:07:18 -0700126 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
127 that->bounds(), caps)) {
128 return false;
129 }
130
msarettfebb2242016-08-26 12:49:27 -0700131 if (fViewMatrix != that->fViewMatrix) {
132 return false;
133 }
134
msarettcc319b92016-08-25 18:07:18 -0700135 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;
msarettcc319b92016-08-25 18:07:18 -0700142 SkRegion fRegion;
143 };
144
msarettfebb2242016-08-26 12:49:27 -0700145 SkMatrix fViewMatrix;
msarettcc319b92016-08-25 18:07:18 -0700146 SkSTArray<1, RegionInfo, true> fRegions;
147
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400148 typedef GrLegacyMeshDrawOp INHERITED;
msarettcc319b92016-08-25 18:07:18 -0700149};
150
Brian Salomonfc527d22016-12-14 21:07:01 -0500151namespace GrRegionOp {
msarettcc319b92016-08-25 18:07:18 -0700152
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400153std::unique_ptr<GrLegacyMeshDrawOp> Make(GrColor color, const SkMatrix& viewMatrix,
154 const SkRegion& region) {
155 return std::unique_ptr<GrLegacyMeshDrawOp>(new RegionOp(color, viewMatrix, region));
msarettcc319b92016-08-25 18:07:18 -0700156}
Brian Salomonfc527d22016-12-14 21:07:01 -0500157}