blob: af83aa629de483360e839e852eed8e2707e12302 [file] [log] [blame]
joshualitt33a5fce2015-11-18 13:28:51 -08001/*
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
Brian Salomonfc527d22016-12-14 21:07:01 -05008#include "GrLatticeOp.h"
joshualitt33a5fce2015-11-18 13:28:51 -08009
joshualitt33a5fce2015-11-18 13:28:51 -080010#include "GrDefaultGeoProcFactory.h"
Brian Salomondad29232016-12-01 16:40:24 -050011#include "GrMeshDrawOp.h"
Brian Salomon742e31d2016-12-07 17:06:19 -050012#include "GrOpFlushState.h"
joshualitt33a5fce2015-11-18 13:28:51 -080013#include "GrResourceProvider.h"
joshualitt33a5fce2015-11-18 13:28:51 -080014#include "SkBitmap.h"
msarettc573a402016-08-02 08:05:56 -070015#include "SkLatticeIter.h"
joshualitt33a5fce2015-11-18 13:28:51 -080016#include "SkRect.h"
17
bungeman06ca8ec2016-06-09 08:01:03 -070018static sk_sp<GrGeometryProcessor> create_gp(bool readsCoverage) {
joshualitt33a5fce2015-11-18 13:28:51 -080019 using namespace GrDefaultGeoProcFactory;
20 Color color(Color::kAttribute_Type);
21 Coverage coverage(readsCoverage ? Coverage::kSolid_Type : Coverage::kNone_Type);
22 LocalCoords localCoords(LocalCoords::kHasExplicit_Type);
bungeman06ca8ec2016-06-09 08:01:03 -070023 return GrDefaultGeoProcFactory::Make(color, coverage, localCoords, SkMatrix::I());
joshualitt33a5fce2015-11-18 13:28:51 -080024}
25
Brian Salomonfc527d22016-12-14 21:07:01 -050026class NonAALatticeOp final : public GrMeshDrawOp {
joshualitt33a5fce2015-11-18 13:28:51 -080027public:
Brian Salomon25a88092016-12-01 09:36:50 -050028 DEFINE_OP_CLASS_ID
joshualitt33a5fce2015-11-18 13:28:51 -080029
30 static const int kVertsPerRect = 4;
31 static const int kIndicesPerRect = 6;
joshualitt33a5fce2015-11-18 13:28:51 -080032
Brian Salomonfc527d22016-12-14 21:07:01 -050033 NonAALatticeOp(GrColor color, const SkMatrix& viewMatrix, int imageWidth, int imageHeight,
34 std::unique_ptr<SkLatticeIter> iter, const SkRect& dst)
35 : INHERITED(ClassID()) {
bsalomona71b8982016-06-30 12:13:52 -070036 Patch& patch = fPatches.push_back();
37 patch.fViewMatrix = viewMatrix;
38 patch.fColor = color;
msarett10e3d9b2016-08-18 15:46:03 -070039 patch.fIter = std::move(iter);
bsalomona71b8982016-06-30 12:13:52 -070040 patch.fDst = dst;
joshualitt33a5fce2015-11-18 13:28:51 -080041
42 fImageWidth = imageWidth;
43 fImageHeight = imageHeight;
44
45 // setup bounds
bsalomon88cf17d2016-07-08 06:40:56 -070046 this->setTransformedBounds(patch.fDst, viewMatrix, HasAABloat::kNo, IsZeroArea::kNo);
joshualitt33a5fce2015-11-18 13:28:51 -080047 }
48
Brian Salomonfc527d22016-12-14 21:07:01 -050049 const char* name() const override { return "NonAALatticeOp"; }
robertphillips783a4da2015-11-19 14:00:02 -080050
51 SkString dumpInfo() const override {
52 SkString str;
53
bsalomona71b8982016-06-30 12:13:52 -070054 for (int i = 0; i < fPatches.count(); ++i) {
Brian Salomonfc527d22016-12-14 21:07:01 -050055 str.appendf("%d: Color: 0x%08x Dst [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n", i,
56 fPatches[i].fColor, fPatches[i].fDst.fLeft, fPatches[i].fDst.fTop,
bsalomona71b8982016-06-30 12:13:52 -070057 fPatches[i].fDst.fRight, fPatches[i].fDst.fBottom);
robertphillips783a4da2015-11-19 14:00:02 -080058 }
59
Brian Salomon7c3e7182016-12-01 09:35:30 -050060 str.append(DumpPipelineInfo(*this->pipeline()));
robertphillips783a4da2015-11-19 14:00:02 -080061 str.append(INHERITED::dumpInfo());
62 return str;
63 }
joshualitt33a5fce2015-11-18 13:28:51 -080064
Brian Salomon92aee3d2016-12-21 09:20:25 -050065private:
66 void getPipelineAnalysisInput(GrPipelineAnalysisDrawOpInput* input) const override {
67 input->pipelineColorInput()->setUnknownFourComponents();
68 input->pipelineCoverageInput()->setKnownSingleComponent(0xff);
joshualitt33a5fce2015-11-18 13:28:51 -080069 }
70
Brian Salomon92aee3d2016-12-21 09:20:25 -050071 void applyPipelineOptimizations(const GrPipelineOptimizations& analysioptimizations) override {
72 analysioptimizations.getOverrideColorIfSet(&fPatches[0].fColor);
73 fOptimizations = analysioptimizations;
74 }
75
joshualitt144c3c82015-11-30 12:30:13 -080076 void onPrepareDraws(Target* target) const override {
Brian Salomon92aee3d2016-12-21 09:20:25 -050077 sk_sp<GrGeometryProcessor> gp(create_gp(fOptimizations.readsCoverage()));
joshualitt33a5fce2015-11-18 13:28:51 -080078 if (!gp) {
79 SkDebugf("Couldn't create GrGeometryProcessor\n");
80 return;
81 }
82
joshualitt33a5fce2015-11-18 13:28:51 -080083 size_t vertexStride = gp->getVertexStride();
bsalomona71b8982016-06-30 12:13:52 -070084 int patchCnt = fPatches.count();
msarett10e3d9b2016-08-18 15:46:03 -070085 int numRects = 0;
86 for (int i = 0; i < patchCnt; i++) {
msarett0764efe2016-09-02 11:24:30 -070087 numRects += fPatches[i].fIter->numRectsToDraw();
msarett10e3d9b2016-08-18 15:46:03 -070088 }
joshualitt33a5fce2015-11-18 13:28:51 -080089
Hal Canary144caf52016-11-07 17:57:18 -050090 sk_sp<const GrBuffer> indexBuffer(target->resourceProvider()->refQuadIndexBuffer());
joshualitt33a5fce2015-11-18 13:28:51 -080091 InstancedHelper helper;
92 void* vertices = helper.init(target, kTriangles_GrPrimitiveType, vertexStride,
Brian Salomonfc527d22016-12-14 21:07:01 -050093 indexBuffer.get(), kVertsPerRect, kIndicesPerRect, numRects);
joshualitt33a5fce2015-11-18 13:28:51 -080094 if (!vertices || !indexBuffer) {
95 SkDebugf("Could not allocate vertices\n");
96 return;
97 }
98
msarett10e3d9b2016-08-18 15:46:03 -070099 intptr_t verts = reinterpret_cast<intptr_t>(vertices);
bsalomona71b8982016-06-30 12:13:52 -0700100 for (int i = 0; i < patchCnt; i++) {
msarett7fc08582016-08-18 14:29:22 -0700101 const Patch& patch = fPatches[i];
msarett10e3d9b2016-08-18 15:46:03 -0700102
103 // Apply the view matrix here if it is scale-translate. Otherwise, we need to
104 // wait until we've created the dst rects.
105 bool isScaleTranslate = patch.fViewMatrix.isScaleTranslate();
106 if (isScaleTranslate) {
107 patch.fIter->mapDstScaleTranslate(patch.fViewMatrix);
108 }
joshualitt33a5fce2015-11-18 13:28:51 -0800109
110 SkRect srcR, dstR;
msarett10e3d9b2016-08-18 15:46:03 -0700111 intptr_t patchVerts = verts;
112 while (patch.fIter->next(&srcR, &dstR)) {
joshualitt33a5fce2015-11-18 13:28:51 -0800113 SkPoint* positions = reinterpret_cast<SkPoint*>(verts);
Brian Salomonfc527d22016-12-14 21:07:01 -0500114 positions->setRectFan(dstR.fLeft, dstR.fTop, dstR.fRight, dstR.fBottom,
115 vertexStride);
joshualitt33a5fce2015-11-18 13:28:51 -0800116
joshualitt33a5fce2015-11-18 13:28:51 -0800117 // Setup local coords
118 static const int kLocalOffset = sizeof(SkPoint) + sizeof(GrColor);
119 SkPoint* coords = reinterpret_cast<SkPoint*>(verts + kLocalOffset);
120 coords->setRectFan(srcR.fLeft, srcR.fTop, srcR.fRight, srcR.fBottom, vertexStride);
121
122 static const int kColorOffset = sizeof(SkPoint);
123 GrColor* vertColor = reinterpret_cast<GrColor*>(verts + kColorOffset);
124 for (int j = 0; j < 4; ++j) {
bsalomona71b8982016-06-30 12:13:52 -0700125 *vertColor = patch.fColor;
Brian Salomonfc527d22016-12-14 21:07:01 -0500126 vertColor = (GrColor*)((intptr_t)vertColor + vertexStride);
joshualitt33a5fce2015-11-18 13:28:51 -0800127 }
128 verts += kVertsPerRect * vertexStride;
129 }
msarett10e3d9b2016-08-18 15:46:03 -0700130
131 // If we didn't handle it above, apply the matrix here.
132 if (!isScaleTranslate) {
133 SkPoint* positions = reinterpret_cast<SkPoint*>(patchVerts);
Brian Salomonfc527d22016-12-14 21:07:01 -0500134 patch.fViewMatrix.mapPointsWithStride(
135 positions, vertexStride, kVertsPerRect * patch.fIter->numRectsToDraw());
msarett10e3d9b2016-08-18 15:46:03 -0700136 }
joshualitt33a5fce2015-11-18 13:28:51 -0800137 }
bungeman06ca8ec2016-06-09 08:01:03 -0700138 helper.recordDraw(target, gp.get());
joshualitt33a5fce2015-11-18 13:28:51 -0800139 }
140
Brian Salomon25a88092016-12-01 09:36:50 -0500141 bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
Brian Salomonfc527d22016-12-14 21:07:01 -0500142 NonAALatticeOp* that = t->cast<NonAALatticeOp>();
joshualitt33a5fce2015-11-18 13:28:51 -0800143 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
144 that->bounds(), caps)) {
145 return false;
146 }
147
148 SkASSERT(this->fImageWidth == that->fImageWidth &&
149 this->fImageHeight == that->fImageHeight);
150
Brian Salomonfc527d22016-12-14 21:07:01 -0500151 // In the event of two ops, one who can tweak, one who cannot, we just fall back to not
152 // tweaking.
Brian Salomon92aee3d2016-12-21 09:20:25 -0500153 if (fOptimizations.canTweakAlphaForCoverage() &&
154 !that->fOptimizations.canTweakAlphaForCoverage()) {
155 fOptimizations = that->fOptimizations;
joshualitt33a5fce2015-11-18 13:28:51 -0800156 }
157
msarett10e3d9b2016-08-18 15:46:03 -0700158 fPatches.move_back_n(that->fPatches.count(), that->fPatches.begin());
bsalomon88cf17d2016-07-08 06:40:56 -0700159 this->joinBounds(*that);
joshualitt33a5fce2015-11-18 13:28:51 -0800160 return true;
161 }
162
bsalomona71b8982016-06-30 12:13:52 -0700163 struct Patch {
164 SkMatrix fViewMatrix;
msarett10e3d9b2016-08-18 15:46:03 -0700165 std::unique_ptr<SkLatticeIter> fIter;
bsalomona71b8982016-06-30 12:13:52 -0700166 SkRect fDst;
167 GrColor fColor;
168 };
169
Brian Salomon92aee3d2016-12-21 09:20:25 -0500170 GrPipelineOptimizations fOptimizations;
joshualitt33a5fce2015-11-18 13:28:51 -0800171 int fImageWidth;
172 int fImageHeight;
bsalomona71b8982016-06-30 12:13:52 -0700173 SkSTArray<1, Patch, true> fPatches;
joshualitt33a5fce2015-11-18 13:28:51 -0800174
Brian Salomondad29232016-12-01 16:40:24 -0500175 typedef GrMeshDrawOp INHERITED;
joshualitt33a5fce2015-11-18 13:28:51 -0800176};
177
Brian Salomonfc527d22016-12-14 21:07:01 -0500178namespace GrLatticeOp {
179sk_sp<GrDrawOp> MakeNonAA(GrColor color, const SkMatrix& viewMatrix, int imageWidth,
180 int imageHeight, std::unique_ptr<SkLatticeIter> iter, const SkRect& dst) {
181 return sk_sp<GrDrawOp>(
182 new NonAALatticeOp(color, viewMatrix, imageWidth, imageHeight, std::move(iter), dst));
joshualitt33a5fce2015-11-18 13:28:51 -0800183}
184};