GrRegionOp.cpp revision 8c852be264d003b2e610c5b8634bc0f81c46bbba
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
8fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon#include "GrRegionOp.h"
9cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
10dad2923b8ec9270d810c1e8e76da8e6768d8f9ddBrian Salomon#include "GrDefaultGeoProcFactory.h"
11dad2923b8ec9270d810c1e8e76da8e6768d8f9ddBrian Salomon#include "GrMeshDrawOp.h"
12742e31de1599f3902810aecdf2e2e3eed3b40a09Brian Salomon#include "GrOpFlushState.h"
13cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett#include "GrResourceProvider.h"
14cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett#include "SkMatrixPriv.h"
15cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett#include "SkRegion.h"
16cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
17cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarettstatic const int kVertsPerInstance = 4;
18cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarettstatic const int kIndicesPerInstance = 6;
19cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
208c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomonstatic sk_sp<GrGeometryProcessor> make_gp(const SkMatrix& viewMatrix) {
21cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    using namespace GrDefaultGeoProcFactory;
228c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon    return GrDefaultGeoProcFactory::Make(Color::kAttribute_Type, Coverage::kSolid_Type,
238c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon                                         LocalCoords::kUsePosition_Type, viewMatrix);
24cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett}
25cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
26febb22469999b928850182ebc57bfd6fbd7402d6msarettstatic void tesselate_region(intptr_t vertices,
27fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon                             size_t vertexStride,
28fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon                             GrColor color,
29fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon                             const SkRegion& region) {
30cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    SkRegion::Iterator iter(region);
31cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
32cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    intptr_t verts = vertices;
33cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    while (!iter.done()) {
34febb22469999b928850182ebc57bfd6fbd7402d6msarett        SkRect rect = SkRect::Make(iter.rect());
35fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon        SkPoint* position = (SkPoint*)verts;
36febb22469999b928850182ebc57bfd6fbd7402d6msarett        position->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vertexStride);
37cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
38cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        static const int kColorOffset = sizeof(SkPoint);
39cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        GrColor* vertColor = reinterpret_cast<GrColor*>(verts + kColorOffset);
40cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        for (int i = 0; i < kVertsPerInstance; i++) {
41cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett            *vertColor = color;
42fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon            vertColor = (GrColor*)((intptr_t)vertColor + vertexStride);
43cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        }
44cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
45cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        verts += vertexStride * kVertsPerInstance;
46cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        iter.next();
47cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    }
48cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett}
49cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
50fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomonclass RegionOp final : public GrMeshDrawOp {
51cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarettpublic:
5225a880960a9a689a745a01071ecba3fe494b5940Brian Salomon    DEFINE_OP_CLASS_ID
53cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
54fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon    RegionOp(GrColor color, const SkMatrix& viewMatrix, const SkRegion& region)
55fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon            : INHERITED(ClassID()), fViewMatrix(viewMatrix) {
56cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        RegionInfo& info = fRegions.push_back();
57cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        info.fColor = color;
58cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        info.fRegion = region;
59cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
60cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        SkRect bounds = SkRect::Make(region.getBounds());
61cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        this->setTransformedBounds(bounds, viewMatrix, HasAABloat::kNo, IsZeroArea::kNo);
62cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    }
63cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
64fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon    const char* name() const override { return "GrRegionOp"; }
65cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
66cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    SkString dumpInfo() const override {
67cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        SkString str;
6853e4c3c0da40b58638d05e0f753ab6d450b961f5Brian Salomon        str.appendf("# combined: %d\n", fRegions.count());
69cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        for (int i = 0; i < fRegions.count(); ++i) {
70cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett            const RegionInfo& info = fRegions[i];
71fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon            str.appendf("%d: Color: 0x%08x, Region with %d rects\n", i, info.fColor,
72fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon                        info.fRegion.computeRegionComplexity());
73cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        }
747c3e7180948766321c51d165737555e78910de51Brian Salomon        str.append(DumpPipelineInfo(*this->pipeline()));
75cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        str.append(INHERITED::dumpInfo());
76cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        return str;
77cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    }
78cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
7992aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomonprivate:
8092aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon    void getPipelineAnalysisInput(GrPipelineAnalysisDrawOpInput* input) const override {
8192aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon        input->pipelineColorInput()->setKnownFourComponents(fRegions[0].fColor);
8292aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon        input->pipelineCoverageInput()->setKnownSingleComponent(0xff);
83cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    }
84cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
8592aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon    void applyPipelineOptimizations(const GrPipelineOptimizations& optimizations) override {
8692aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon        optimizations.getOverrideColorIfSet(&fRegions[0].fColor);
8792aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon        fOptimizations = optimizations;
88cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    }
89cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
90cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    void onPrepareDraws(Target* target) const override {
918c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon        sk_sp<GrGeometryProcessor> gp = make_gp(fViewMatrix);
92cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        if (!gp) {
93cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett            SkDebugf("Couldn't create GrGeometryProcessor\n");
94cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett            return;
95cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        }
96febb22469999b928850182ebc57bfd6fbd7402d6msarett        SkASSERT(gp->getVertexStride() == sizeof(GrDefaultGeoProcFactory::PositionColorAttr));
97cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
98cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        int numRegions = fRegions.count();
99cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        int numRects = 0;
100cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        for (int i = 0; i < numRegions; i++) {
101cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett            numRects += fRegions[i].fRegion.computeRegionComplexity();
102cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        }
103cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
104cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        size_t vertexStride = gp->getVertexStride();
105144caf55ffc692bcda77703a73bb9a894f7d024fHal Canary        sk_sp<const GrBuffer> indexBuffer(target->resourceProvider()->refQuadIndexBuffer());
106cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        InstancedHelper helper;
107fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon        void* vertices =
108fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon                helper.init(target, kTriangles_GrPrimitiveType, vertexStride, indexBuffer.get(),
109fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon                            kVertsPerInstance, kIndicesPerInstance, numRects);
110cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        if (!vertices || !indexBuffer) {
111cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett            SkDebugf("Could not allocate vertices\n");
112cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett            return;
113cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        }
114cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
115cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        intptr_t verts = reinterpret_cast<intptr_t>(vertices);
116cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        for (int i = 0; i < numRegions; i++) {
117febb22469999b928850182ebc57bfd6fbd7402d6msarett            tesselate_region(verts, vertexStride, fRegions[i].fColor, fRegions[i].fRegion);
118febb22469999b928850182ebc57bfd6fbd7402d6msarett            int numRectsInRegion = fRegions[i].fRegion.computeRegionComplexity();
119cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett            verts += numRectsInRegion * kVertsPerInstance * vertexStride;
120cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        }
121cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        helper.recordDraw(target, gp.get());
122cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    }
123cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
12425a880960a9a689a745a01071ecba3fe494b5940Brian Salomon    bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
125fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon        RegionOp* that = t->cast<RegionOp>();
126cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
127cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett                                    that->bounds(), caps)) {
128cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett            return false;
129cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        }
130cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
131febb22469999b928850182ebc57bfd6fbd7402d6msarett        if (fViewMatrix != that->fViewMatrix) {
132febb22469999b928850182ebc57bfd6fbd7402d6msarett            return false;
133febb22469999b928850182ebc57bfd6fbd7402d6msarett        }
134febb22469999b928850182ebc57bfd6fbd7402d6msarett
135cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        fRegions.push_back_n(that->fRegions.count(), that->fRegions.begin());
136cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        this->joinBounds(*that);
137cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        return true;
138cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    }
139cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
140cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    struct RegionInfo {
141cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        GrColor fColor;
142cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett        SkRegion fRegion;
143cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    };
144cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
145febb22469999b928850182ebc57bfd6fbd7402d6msarett    SkMatrix fViewMatrix;
14692aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon    GrPipelineOptimizations fOptimizations;
147cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett    SkSTArray<1, RegionInfo, true> fRegions;
148cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
149dad2923b8ec9270d810c1e8e76da8e6768d8f9ddBrian Salomon    typedef GrMeshDrawOp INHERITED;
150cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett};
151cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
152fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomonnamespace GrRegionOp {
153cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett
154f8334781914363caf537f22f012fcd5c03c60dadBrian Salomonstd::unique_ptr<GrDrawOp> Make(GrColor color, const SkMatrix& viewMatrix, const SkRegion& region) {
155f8334781914363caf537f22f012fcd5c03c60dadBrian Salomon    return std::unique_ptr<GrDrawOp>(new RegionOp(color, viewMatrix, region));
156fc527d27641bb693a0a7703ba9d35100f7500fd7Brian Salomon}
157cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett}
158