Line data Source code
1 : /*
2 : * Copyright 2015 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 "GrLatticeOp.h"
9 :
10 : #include "GrDefaultGeoProcFactory.h"
11 : #include "GrMeshDrawOp.h"
12 : #include "GrOpFlushState.h"
13 : #include "GrResourceProvider.h"
14 : #include "SkBitmap.h"
15 : #include "SkLatticeIter.h"
16 : #include "SkRect.h"
17 :
18 0 : static sk_sp<GrGeometryProcessor> create_gp() {
19 : using namespace GrDefaultGeoProcFactory;
20 : return GrDefaultGeoProcFactory::Make(Color::kPremulGrColorAttribute_Type, Coverage::kSolid_Type,
21 0 : LocalCoords::kHasExplicit_Type, SkMatrix::I());
22 : }
23 :
24 0 : class NonAALatticeOp final : public GrLegacyMeshDrawOp {
25 : public:
26 0 : DEFINE_OP_CLASS_ID
27 :
28 : static const int kVertsPerRect = 4;
29 : static const int kIndicesPerRect = 6;
30 :
31 0 : NonAALatticeOp(GrColor color, const SkMatrix& viewMatrix, int imageWidth, int imageHeight,
32 : std::unique_ptr<SkLatticeIter> iter, const SkRect& dst)
33 0 : : INHERITED(ClassID()) {
34 0 : Patch& patch = fPatches.push_back();
35 0 : patch.fViewMatrix = viewMatrix;
36 0 : patch.fColor = color;
37 0 : patch.fIter = std::move(iter);
38 0 : patch.fDst = dst;
39 :
40 0 : fImageWidth = imageWidth;
41 0 : fImageHeight = imageHeight;
42 :
43 : // setup bounds
44 0 : this->setTransformedBounds(patch.fDst, viewMatrix, HasAABloat::kNo, IsZeroArea::kNo);
45 0 : }
46 :
47 0 : const char* name() const override { return "NonAALatticeOp"; }
48 :
49 0 : SkString dumpInfo() const override {
50 0 : SkString str;
51 :
52 0 : for (int i = 0; i < fPatches.count(); ++i) {
53 0 : str.appendf("%d: Color: 0x%08x Dst [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n", i,
54 0 : fPatches[i].fColor, fPatches[i].fDst.fLeft, fPatches[i].fDst.fTop,
55 0 : fPatches[i].fDst.fRight, fPatches[i].fDst.fBottom);
56 : }
57 :
58 0 : str.append(DumpPipelineInfo(*this->pipeline()));
59 0 : str.append(INHERITED::dumpInfo());
60 0 : return str;
61 : }
62 :
63 : private:
64 0 : void getProcessorAnalysisInputs(GrProcessorAnalysisColor* color,
65 : GrProcessorAnalysisCoverage* coverage) const override {
66 0 : color->setToUnknown();
67 0 : *coverage = GrProcessorAnalysisCoverage::kNone;
68 0 : }
69 :
70 0 : void applyPipelineOptimizations(const PipelineOptimizations& analysioptimizations) override {
71 0 : analysioptimizations.getOverrideColorIfSet(&fPatches[0].fColor);
72 0 : }
73 :
74 0 : void onPrepareDraws(Target* target) const override {
75 0 : sk_sp<GrGeometryProcessor> gp(create_gp());
76 0 : if (!gp) {
77 0 : SkDebugf("Couldn't create GrGeometryProcessor\n");
78 0 : return;
79 : }
80 :
81 0 : size_t vertexStride = gp->getVertexStride();
82 0 : int patchCnt = fPatches.count();
83 0 : int numRects = 0;
84 0 : for (int i = 0; i < patchCnt; i++) {
85 0 : numRects += fPatches[i].fIter->numRectsToDraw();
86 : }
87 :
88 0 : sk_sp<const GrBuffer> indexBuffer(target->resourceProvider()->refQuadIndexBuffer());
89 0 : InstancedHelper helper;
90 0 : void* vertices = helper.init(target, kTriangles_GrPrimitiveType, vertexStride,
91 0 : indexBuffer.get(), kVertsPerRect, kIndicesPerRect, numRects);
92 0 : if (!vertices || !indexBuffer) {
93 0 : SkDebugf("Could not allocate vertices\n");
94 0 : return;
95 : }
96 :
97 0 : intptr_t verts = reinterpret_cast<intptr_t>(vertices);
98 0 : for (int i = 0; i < patchCnt; i++) {
99 0 : const Patch& patch = fPatches[i];
100 :
101 : // Apply the view matrix here if it is scale-translate. Otherwise, we need to
102 : // wait until we've created the dst rects.
103 0 : bool isScaleTranslate = patch.fViewMatrix.isScaleTranslate();
104 0 : if (isScaleTranslate) {
105 0 : patch.fIter->mapDstScaleTranslate(patch.fViewMatrix);
106 : }
107 :
108 : SkRect srcR, dstR;
109 0 : intptr_t patchVerts = verts;
110 0 : while (patch.fIter->next(&srcR, &dstR)) {
111 0 : SkPoint* positions = reinterpret_cast<SkPoint*>(verts);
112 0 : positions->setRectFan(dstR.fLeft, dstR.fTop, dstR.fRight, dstR.fBottom,
113 0 : vertexStride);
114 :
115 : // Setup local coords
116 : static const int kLocalOffset = sizeof(SkPoint) + sizeof(GrColor);
117 0 : SkPoint* coords = reinterpret_cast<SkPoint*>(verts + kLocalOffset);
118 0 : coords->setRectFan(srcR.fLeft, srcR.fTop, srcR.fRight, srcR.fBottom, vertexStride);
119 :
120 : static const int kColorOffset = sizeof(SkPoint);
121 0 : GrColor* vertColor = reinterpret_cast<GrColor*>(verts + kColorOffset);
122 0 : for (int j = 0; j < 4; ++j) {
123 0 : *vertColor = patch.fColor;
124 0 : vertColor = (GrColor*)((intptr_t)vertColor + vertexStride);
125 : }
126 0 : verts += kVertsPerRect * vertexStride;
127 : }
128 :
129 : // If we didn't handle it above, apply the matrix here.
130 0 : if (!isScaleTranslate) {
131 0 : SkPoint* positions = reinterpret_cast<SkPoint*>(patchVerts);
132 0 : patch.fViewMatrix.mapPointsWithStride(
133 0 : positions, vertexStride, kVertsPerRect * patch.fIter->numRectsToDraw());
134 : }
135 : }
136 0 : helper.recordDraw(target, gp.get(), this->pipeline());
137 : }
138 :
139 0 : bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
140 0 : NonAALatticeOp* that = t->cast<NonAALatticeOp>();
141 0 : if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
142 : that->bounds(), caps)) {
143 0 : return false;
144 : }
145 :
146 0 : SkASSERT(this->fImageWidth == that->fImageWidth &&
147 : this->fImageHeight == that->fImageHeight);
148 :
149 0 : fPatches.move_back_n(that->fPatches.count(), that->fPatches.begin());
150 0 : this->joinBounds(*that);
151 0 : return true;
152 : }
153 :
154 0 : struct Patch {
155 : SkMatrix fViewMatrix;
156 : std::unique_ptr<SkLatticeIter> fIter;
157 : SkRect fDst;
158 : GrColor fColor;
159 : };
160 :
161 : int fImageWidth;
162 : int fImageHeight;
163 : SkSTArray<1, Patch, true> fPatches;
164 :
165 : typedef GrLegacyMeshDrawOp INHERITED;
166 : };
167 :
168 : namespace GrLatticeOp {
169 0 : std::unique_ptr<GrLegacyMeshDrawOp> MakeNonAA(GrColor color, const SkMatrix& viewMatrix,
170 : int imageWidth, int imageHeight,
171 : std::unique_ptr<SkLatticeIter> iter,
172 : const SkRect& dst) {
173 : return std::unique_ptr<GrLegacyMeshDrawOp>(
174 0 : new NonAALatticeOp(color, viewMatrix, imageWidth, imageHeight, std::move(iter), dst));
175 : }
176 : };
|