GrRegionOp.cpp revision cc319b95a58ae15e88c3c028b8726e7cab9121ff
1cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett/*
2cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett * Copyright 2016 Google Inc.
3cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett *
4cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett * Use of this source code is governed by a BSD-style license that can be
5cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett * found in the LICENSE file.
6cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett */
7cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
8cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett#include "GrRegionBatch.h"
9cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
10cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett#include "GrDefaultGeoProcFactory.h"
11cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett#include "GrBatchFlushState.h"
12cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett#include "GrResourceProvider.h"
13cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett#include "GrVertexBatch.h"
14cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett#include "SkMatrixPriv.h"
15cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett#include "SkRegion.h"
16cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
17cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarettstatic const int kVertsPerInstance = 4;
18cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarettstatic const int kIndicesPerInstance = 6;
19cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
20cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarettstatic sk_sp<GrGeometryProcessor> make_gp(bool readsCoverage) {
21cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    using namespace GrDefaultGeoProcFactory;
22cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    Color color(Color::kAttribute_Type);
23cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    Coverage coverage(readsCoverage ? Coverage::kSolid_Type : Coverage::kNone_Type);
24cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
25cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    LocalCoords localCoords(LocalCoords::kHasExplicit_Type);
26cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    return GrDefaultGeoProcFactory::Make(color, coverage, localCoords, SkMatrix::I());
27cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett}
28cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
29cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarettstatic int tesselate_region(intptr_t vertices,
30cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett                            size_t vertexStride,
31cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett                            GrColor color,
32cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett                            const SkMatrix& viewMatrix,
33cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett                            const SkRegion& region) {
34cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    SkRegion::Iterator iter(region);
35cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
36cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    intptr_t verts = vertices;
37cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    while (!iter.done()) {
38cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        SkIRect rect = iter.rect();
39cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        SkPoint* position = (SkPoint*) verts;
40cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        position->setIRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vertexStride);
41cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
42cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        static const int kLocalOffset = sizeof(SkPoint) + sizeof(GrColor);
43cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        SkPoint* localPosition = (SkPoint*) (verts + kLocalOffset);
44cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        localPosition->setIRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vertexStride);
45cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
46cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        static const int kColorOffset = sizeof(SkPoint);
47cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        GrColor* vertColor = reinterpret_cast<GrColor*>(verts + kColorOffset);
48cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        for (int i = 0; i < kVertsPerInstance; i++) {
49cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett            *vertColor = color;
50cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett            vertColor = (GrColor*) ((intptr_t) vertColor + vertexStride);
51cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        }
52cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
53cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        verts += vertexStride * kVertsPerInstance;
54cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        iter.next();
55cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    }
56cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
57cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    SkPoint* positions = reinterpret_cast<SkPoint*>(vertices);
58cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    int numRects = region.computeRegionComplexity();
59cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    SkMatrixPriv::MapPointsWithStride(viewMatrix, positions, vertexStride,
60cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett                                      numRects * kVertsPerInstance);
61cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
62cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    return numRects;
63cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett}
64cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
65cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarettclass RegionBatch : public GrVertexBatch {
66cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarettpublic:
67cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    DEFINE_BATCH_CLASS_ID
68cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
69cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    RegionBatch(GrColor color, const SkMatrix& viewMatrix, const SkRegion& region)
70cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett            : INHERITED(ClassID()) {
71cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
72cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        RegionInfo& info = fRegions.push_back();
73cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        info.fColor = color;
74cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        info.fViewMatrix = viewMatrix;
75cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        info.fRegion = region;
76cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
77cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        SkRect bounds = SkRect::Make(region.getBounds());
78cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        this->setTransformedBounds(bounds, viewMatrix, HasAABloat::kNo, IsZeroArea::kNo);
79cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    }
80cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
81cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    const char* name() const override { return "GrRegionBatch"; }
82cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
83cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    SkString dumpInfo() const override {
84cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        SkString str;
85cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        str.appendf("# batched: %d\n", fRegions.count());
86cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        for (int i = 0; i < fRegions.count(); ++i) {
87cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett            const RegionInfo& info = fRegions[i];
88cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett            str.appendf("%d: Color: 0x%08x, Region with %d rects\n",
89cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett                        i, info.fColor, info.fRegion.computeRegionComplexity());
90cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        }
91cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        str.append(INHERITED::dumpInfo());
92cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        return str;
93cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    }
94cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
95cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    void computePipelineOptimizations(GrInitInvariantOutput* color,
96cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett                                      GrInitInvariantOutput* coverage,
97cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett                                      GrBatchToXPOverrides* overrides) const override {
98cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        // When this is called on a batch, there is only one region.
99cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        color->setKnownFourComponents(fRegions[0].fColor);
100cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        coverage->setKnownSingleComponent(0xff);
101cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    }
102cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
103cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    void initBatchTracker(const GrXPOverridesForBatch& overrides) override {
104cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        overrides.getOverrideColorIfSet(&fRegions[0].fColor);
105cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        fOverrides = overrides;
106cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    }
107cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
108cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarettprivate:
109cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
110cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    void onPrepareDraws(Target* target) const override {
111cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        sk_sp<GrGeometryProcessor> gp = make_gp(fOverrides.readsCoverage());
112cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        if (!gp) {
113cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett            SkDebugf("Couldn't create GrGeometryProcessor\n");
114cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett            return;
115cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        }
116cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        SkASSERT(gp->getVertexStride() ==
117cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett                sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoordAttr));
118cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
119cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        int numRegions = fRegions.count();
120cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        int numRects = 0;
121cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        for (int i = 0; i < numRegions; i++) {
122cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett            numRects += fRegions[i].fRegion.computeRegionComplexity();
123cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        }
124cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
125cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        size_t vertexStride = gp->getVertexStride();
126cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        SkAutoTUnref<const GrBuffer> indexBuffer(target->resourceProvider()->refQuadIndexBuffer());
127cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        InstancedHelper helper;
128cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        void* vertices = helper.init(target, kTriangles_GrPrimitiveType, vertexStride,
129cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett                                     indexBuffer, kVertsPerInstance, kIndicesPerInstance, numRects);
130cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        if (!vertices || !indexBuffer) {
131cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett            SkDebugf("Could not allocate vertices\n");
132cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett            return;
133cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        }
134cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
135cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        intptr_t verts = reinterpret_cast<intptr_t>(vertices);
136cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        for (int i = 0; i < numRegions; i++) {
137cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett            int numRectsInRegion = tesselate_region(verts, vertexStride, fRegions[i].fColor,
138cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett                                                    fRegions[i].fViewMatrix, fRegions[i].fRegion);
139cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett            verts += numRectsInRegion * kVertsPerInstance * vertexStride;
140cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        }
141cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        helper.recordDraw(target, gp.get());
142cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    }
143cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
144cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override {
145cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        RegionBatch* that = t->cast<RegionBatch>();
146cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
147cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett                                    that->bounds(), caps)) {
148cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett            return false;
149cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        }
150cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
151cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        fRegions.push_back_n(that->fRegions.count(), that->fRegions.begin());
152cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        this->joinBounds(*that);
153cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        return true;
154cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    }
155cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
156cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    struct RegionInfo {
157cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        GrColor fColor;
158cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        SkMatrix fViewMatrix;
159cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        SkRegion fRegion;
160cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    };
161cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
162cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    GrXPOverridesForBatch fOverrides;
163cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    SkSTArray<1, RegionInfo, true> fRegions;
164cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
165cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    typedef GrVertexBatch INHERITED;
166cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett};
167cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
168cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarettnamespace GrRegionBatch {
169cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
170cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarettGrDrawBatch* Create(GrColor color,
171cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett                    const SkMatrix& viewMatrix,
172cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett                    const SkRegion& region) {
173cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    return new RegionBatch(color, viewMatrix, region);
174cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett}
175cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
176cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett};
177