blob: 3aa05bb8713f5d4d3618ce5aceafa344e6414536 [file] [log] [blame]
joshualitt9ff64252015-08-10 09:03:51 -07001/*
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
joshualitt37eb1842015-08-12 06:36:57 -07008#include "GrColor.h"
joshualitt9ff64252015-08-10 09:03:51 -07009#include "GrDefaultGeoProcFactory.h"
Brian Salomondad29232016-12-01 16:40:24 -050010#include "GrMeshDrawOp.h"
Brian Salomon742e31d2016-12-07 17:06:19 -050011#include "GrOpFlushState.h"
Brian Salomonbaaf4392017-06-15 09:59:23 -040012#include "GrRectOpFactory.h"
joshualitt9ff64252015-08-10 09:03:51 -070013#include "GrResourceKey.h"
14#include "GrResourceProvider.h"
joshualitt37eb1842015-08-12 06:36:57 -070015#include "GrTypes.h"
16#include "SkMatrix.h"
Brian Salomon8fb37252018-01-05 10:50:55 -050017#include "SkMatrixPriv.h"
joshualitt37eb1842015-08-12 06:36:57 -070018#include "SkRect.h"
Cary Clark74f623d2017-11-06 20:02:02 -050019#include "SkPointPriv.h"
Brian Salomonbaaf4392017-06-15 09:59:23 -040020#include "ops/GrSimpleMeshDrawOpHelper.h"
Mike Klein79aea6a2018-06-11 10:45:26 -040021#include <new>
joshualitt9ff64252015-08-10 09:03:51 -070022
23GR_DECLARE_STATIC_UNIQUE_KEY(gAAFillRectIndexBufferKey);
24
Brian Salomonbaaf4392017-06-15 09:59:23 -040025static inline bool view_matrix_ok_for_aa_fill_rect(const SkMatrix& viewMatrix) {
26 return viewMatrix.preservesRightAngles();
27}
28
29static inline void set_inset_fan(SkPoint* pts, size_t stride, const SkRect& r, SkScalar dx,
30 SkScalar dy) {
Cary Clark74f623d2017-11-06 20:02:02 -050031 SkPointPriv::SetRectFan(pts, r.fLeft + dx, r.fTop + dy, r.fRight - dx, r.fBottom - dy, stride);
joshualitt9ff64252015-08-10 09:03:51 -070032}
33
joshualitt27801bf2015-08-12 12:52:47 -070034static const int kNumAAFillRectsInIndexBuffer = 256;
35static const int kVertsPerAAFillRect = 8;
36static const int kIndicesPerAAFillRect = 30;
37
Brian Salomond28a79d2017-10-16 13:01:07 -040038static sk_sp<const GrBuffer> get_index_buffer(GrResourceProvider* resourceProvider) {
joshualitt27801bf2015-08-12 12:52:47 -070039 GR_DEFINE_STATIC_UNIQUE_KEY(gAAFillRectIndexBufferKey);
40
Brian Salomon6a639042016-12-14 11:08:17 -050041 // clang-format off
joshualitt27801bf2015-08-12 12:52:47 -070042 static const uint16_t gFillAARectIdx[] = {
43 0, 1, 5, 5, 4, 0,
44 1, 2, 6, 6, 5, 1,
45 2, 3, 7, 7, 6, 2,
46 3, 0, 4, 4, 7, 3,
47 4, 5, 6, 6, 7, 4,
48 };
Brian Salomon6a639042016-12-14 11:08:17 -050049 // clang-format on
50
joshualitt27801bf2015-08-12 12:52:47 -070051 GR_STATIC_ASSERT(SK_ARRAY_COUNT(gFillAARectIdx) == kIndicesPerAAFillRect);
Chris Daltonff926502017-05-03 14:36:54 -040052 return resourceProvider->findOrCreatePatternedIndexBuffer(
Brian Salomon6a639042016-12-14 11:08:17 -050053 gFillAARectIdx, kIndicesPerAAFillRect, kNumAAFillRectsInIndexBuffer,
54 kVertsPerAAFillRect, gAAFillRectIndexBufferKey);
joshualitt27801bf2015-08-12 12:52:47 -070055}
56
joshualittcd47b712015-08-18 07:25:38 -070057static void generate_aa_fill_rect_geometry(intptr_t verts,
58 size_t vertexStride,
59 GrColor color,
60 const SkMatrix& viewMatrix,
61 const SkRect& rect,
62 const SkRect& devRect,
Brian Salomonecea86a2017-01-04 13:25:17 -050063 bool tweakAlphaForCoverage,
joshualittcd47b712015-08-18 07:25:38 -070064 const SkMatrix* localMatrix) {
65 SkPoint* fan0Pos = reinterpret_cast<SkPoint*>(verts);
66 SkPoint* fan1Pos = reinterpret_cast<SkPoint*>(verts + 4 * vertexStride);
67
robertphillips0851d2d2016-06-02 05:21:34 -070068 SkScalar inset;
joshualittcd47b712015-08-18 07:25:38 -070069
70 if (viewMatrix.rectStaysRect()) {
robertphillips0851d2d2016-06-02 05:21:34 -070071 inset = SkMinScalar(devRect.width(), SK_Scalar1);
72 inset = SK_ScalarHalf * SkMinScalar(inset, devRect.height());
73
joshualittcd47b712015-08-18 07:25:38 -070074 set_inset_fan(fan0Pos, vertexStride, devRect, -SK_ScalarHalf, -SK_ScalarHalf);
Brian Salomon6a639042016-12-14 11:08:17 -050075 set_inset_fan(fan1Pos, vertexStride, devRect, inset, inset);
joshualittcd47b712015-08-18 07:25:38 -070076 } else {
77 // compute transformed (1, 0) and (0, 1) vectors
Brian Salomon6a639042016-12-14 11:08:17 -050078 SkVector vec[2] = {{viewMatrix[SkMatrix::kMScaleX], viewMatrix[SkMatrix::kMSkewY]},
79 {viewMatrix[SkMatrix::kMSkewX], viewMatrix[SkMatrix::kMScaleY]}};
joshualittcd47b712015-08-18 07:25:38 -070080
robertphillips0851d2d2016-06-02 05:21:34 -070081 SkScalar len1 = SkPoint::Normalize(&vec[0]);
joshualittcd47b712015-08-18 07:25:38 -070082 vec[0].scale(SK_ScalarHalf);
robertphillips0851d2d2016-06-02 05:21:34 -070083 SkScalar len2 = SkPoint::Normalize(&vec[1]);
joshualittcd47b712015-08-18 07:25:38 -070084 vec[1].scale(SK_ScalarHalf);
85
robertphillips0851d2d2016-06-02 05:21:34 -070086 inset = SkMinScalar(len1 * rect.width(), SK_Scalar1);
87 inset = SK_ScalarHalf * SkMinScalar(inset, len2 * rect.height());
88
joshualittcd47b712015-08-18 07:25:38 -070089 // create the rotated rect
Cary Clark74f623d2017-11-06 20:02:02 -050090 SkPointPriv::SetRectFan(fan0Pos, rect.fLeft, rect.fTop, rect.fRight, rect.fBottom,
91 vertexStride);
Brian Salomonfa3783f2018-01-05 13:49:07 -050092 SkMatrixPriv::MapPointsWithStride(viewMatrix, fan0Pos, vertexStride, 4);
joshualittcd47b712015-08-18 07:25:38 -070093
94 // Now create the inset points and then outset the original
95 // rotated points
96
97 // TL
98 *((SkPoint*)((intptr_t)fan1Pos + 0 * vertexStride)) =
Brian Salomon6a639042016-12-14 11:08:17 -050099 *((SkPoint*)((intptr_t)fan0Pos + 0 * vertexStride)) + vec[0] + vec[1];
joshualittcd47b712015-08-18 07:25:38 -0700100 *((SkPoint*)((intptr_t)fan0Pos + 0 * vertexStride)) -= vec[0] + vec[1];
101 // BL
102 *((SkPoint*)((intptr_t)fan1Pos + 1 * vertexStride)) =
Brian Salomon6a639042016-12-14 11:08:17 -0500103 *((SkPoint*)((intptr_t)fan0Pos + 1 * vertexStride)) + vec[0] - vec[1];
joshualittcd47b712015-08-18 07:25:38 -0700104 *((SkPoint*)((intptr_t)fan0Pos + 1 * vertexStride)) -= vec[0] - vec[1];
105 // BR
106 *((SkPoint*)((intptr_t)fan1Pos + 2 * vertexStride)) =
Brian Salomon6a639042016-12-14 11:08:17 -0500107 *((SkPoint*)((intptr_t)fan0Pos + 2 * vertexStride)) - vec[0] - vec[1];
joshualittcd47b712015-08-18 07:25:38 -0700108 *((SkPoint*)((intptr_t)fan0Pos + 2 * vertexStride)) += vec[0] + vec[1];
109 // TR
110 *((SkPoint*)((intptr_t)fan1Pos + 3 * vertexStride)) =
Brian Salomon6a639042016-12-14 11:08:17 -0500111 *((SkPoint*)((intptr_t)fan0Pos + 3 * vertexStride)) - vec[0] + vec[1];
joshualittcd47b712015-08-18 07:25:38 -0700112 *((SkPoint*)((intptr_t)fan0Pos + 3 * vertexStride)) += vec[0] - vec[1];
113 }
114
115 if (localMatrix) {
116 SkMatrix invViewMatrix;
117 if (!viewMatrix.invert(&invViewMatrix)) {
bsalomon4be9a302016-07-06 07:03:26 -0700118 SkDebugf("View matrix is non-invertible, local coords will be wrong.");
joshualittcd47b712015-08-18 07:25:38 -0700119 invViewMatrix = SkMatrix::I();
120 }
121 SkMatrix localCoordMatrix;
122 localCoordMatrix.setConcat(*localMatrix, invViewMatrix);
123 SkPoint* fan0Loc = reinterpret_cast<SkPoint*>(verts + sizeof(SkPoint) + sizeof(GrColor));
Brian Salomon7c2192b2018-01-08 09:47:57 -0500124 SkMatrixPriv::MapPointsWithStride(localCoordMatrix, fan0Loc, vertexStride, fan0Pos,
125 vertexStride, 8);
joshualittcd47b712015-08-18 07:25:38 -0700126 }
127
joshualittcd47b712015-08-18 07:25:38 -0700128 // Make verts point to vertex color and then set all the color and coverage vertex attrs
129 // values.
130 verts += sizeof(SkPoint);
131
132 // The coverage offset is always the last vertex attribute
133 intptr_t coverageOffset = vertexStride - sizeof(GrColor) - sizeof(SkPoint);
134 for (int i = 0; i < 4; ++i) {
135 if (tweakAlphaForCoverage) {
136 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = 0;
137 } else {
138 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color;
139 *reinterpret_cast<float*>(verts + i * vertexStride + coverageOffset) = 0;
140 }
141 }
142
143 int scale;
144 if (inset < SK_ScalarHalf) {
145 scale = SkScalarFloorToInt(512.0f * inset / (inset + SK_ScalarHalf));
146 SkASSERT(scale >= 0 && scale <= 255);
147 } else {
148 scale = 0xff;
149 }
150
151 verts += 4 * vertexStride;
152
153 float innerCoverage = GrNormalizeByteToFloat(scale);
154 GrColor scaledColor = (0xff == scale) ? color : SkAlphaMulQ(color, scale);
155
156 for (int i = 0; i < 4; ++i) {
157 if (tweakAlphaForCoverage) {
158 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = scaledColor;
159 } else {
160 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color;
Brian Salomon6a639042016-12-14 11:08:17 -0500161 *reinterpret_cast<float*>(verts + i * vertexStride + coverageOffset) = innerCoverage;
joshualittcd47b712015-08-18 07:25:38 -0700162 }
163 }
164}
Brian Salomon6a639042016-12-14 11:08:17 -0500165
Brian Salomonbaaf4392017-06-15 09:59:23 -0400166namespace {
167
168class AAFillRectOp final : public GrMeshDrawOp {
169private:
170 using Helper = GrSimpleMeshDrawOpHelperWithStencil;
171
joshualitt2ad37be2015-08-18 10:16:01 -0700172public:
Brian Salomon25a88092016-12-01 09:36:50 -0500173 DEFINE_OP_CLASS_ID
bsalomon4be9a302016-07-06 07:03:26 -0700174
Robert Phillips7c525e62018-06-12 10:11:12 -0400175 static std::unique_ptr<GrDrawOp> Make(GrContext* context,
176 GrPaint&& paint,
Brian Salomonbaaf4392017-06-15 09:59:23 -0400177 const SkMatrix& viewMatrix,
178 const SkRect& rect,
179 const SkRect& devRect,
180 const SkMatrix* localMatrix,
181 const GrUserStencilSettings* stencil) {
182 SkASSERT(view_matrix_ok_for_aa_fill_rect(viewMatrix));
Robert Phillips7c525e62018-06-12 10:11:12 -0400183 return Helper::FactoryHelper<AAFillRectOp>(context, std::move(paint), viewMatrix, rect,
184 devRect, localMatrix, stencil);
Brian Salomonbaaf4392017-06-15 09:59:23 -0400185 }
186
187 AAFillRectOp(const Helper::MakeArgs& helperArgs,
Brian Osmancf860852018-10-31 14:04:39 -0400188 const SkPMColor4f& color,
Brian Salomon6a639042016-12-14 11:08:17 -0500189 const SkMatrix& viewMatrix,
190 const SkRect& rect,
191 const SkRect& devRect,
Brian Salomonbaaf4392017-06-15 09:59:23 -0400192 const SkMatrix* localMatrix,
193 const GrUserStencilSettings* stencil)
194 : INHERITED(ClassID()), fHelper(helperArgs, GrAAType::kCoverage, stencil) {
bsalomon4be9a302016-07-06 07:03:26 -0700195 if (localMatrix) {
196 void* mem = fRectData.push_back_n(sizeof(RectWithLocalMatrixInfo));
197 new (mem) RectWithLocalMatrixInfo(color, viewMatrix, rect, devRect, *localMatrix);
198 } else {
199 void* mem = fRectData.push_back_n(sizeof(RectInfo));
200 new (mem) RectInfo(color, viewMatrix, rect, devRect);
201 }
Brian Salomon6a639042016-12-14 11:08:17 -0500202 IsZeroArea zeroArea =
203 (!rect.width() || !rect.height()) ? IsZeroArea::kYes : IsZeroArea::kNo;
bsalomon88cf17d2016-07-08 06:40:56 -0700204 this->setBounds(devRect, HasAABloat::kYes, zeroArea);
bsalomon4be9a302016-07-06 07:03:26 -0700205 fRectCnt = 1;
bsalomon0fdec8a2016-07-01 06:31:25 -0700206 }
bsalomon08d14152016-06-30 12:45:18 -0700207
Brian Salomon6a639042016-12-14 11:08:17 -0500208 const char* name() const override { return "AAFillRectOp"; }
bsalomon08d14152016-06-30 12:45:18 -0700209
Brian Salomon7d94bb52018-10-12 14:37:19 -0400210 void visitProxies(const VisitProxyFunc& func, VisitorType) const override {
Robert Phillipsb493eeb2017-09-13 13:10:52 -0400211 fHelper.visitProxies(func);
212 }
213
Brian Osman9a390ac2018-11-12 09:47:48 -0500214#ifdef SK_DEBUG
bsalomon08d14152016-06-30 12:45:18 -0700215 SkString dumpInfo() const override {
216 SkString str;
Robert Phillipsf5442bb2017-04-17 14:18:34 -0400217 str.append(INHERITED::dumpInfo());
Brian Salomon53e4c3c2016-12-21 11:38:53 -0500218 str.appendf("# combined: %d\n", fRectCnt);
bsalomon4be9a302016-07-06 07:03:26 -0700219 const RectInfo* info = this->first();
220 for (int i = 0; i < fRectCnt; ++i) {
221 const SkRect& rect = info->rect();
Brian Salomon6a639042016-12-14 11:08:17 -0500222 str.appendf("%d: Color: 0x%08x, Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n", i,
Brian Osmancf860852018-10-31 14:04:39 -0400223 info->color().toBytes_RGBA(), rect.fLeft, rect.fTop, rect.fRight,
Brian Osman1be2b7c2018-10-29 16:07:15 -0400224 rect.fBottom);
bsalomon4be9a302016-07-06 07:03:26 -0700225 info = this->next(info);
bsalomon08d14152016-06-30 12:45:18 -0700226 }
Brian Salomon82dfd3d2017-06-14 12:30:35 -0400227 str += fHelper.dumpInfo();
228 str += INHERITED::dumpInfo();
bsalomon08d14152016-06-30 12:45:18 -0700229 return str;
230 }
Brian Osman9a390ac2018-11-12 09:47:48 -0500231#endif
bsalomon08d14152016-06-30 12:45:18 -0700232
Brian Salomonbaaf4392017-06-15 09:59:23 -0400233 FixedFunctionFlags fixedFunctionFlags() const override { return fHelper.fixedFunctionFlags(); }
234
Brian Osman532b3f92018-07-11 10:02:07 -0400235 RequiresDstTexture finalize(const GrCaps& caps, const GrAppliedClip* clip) override {
Brian Osmancf860852018-10-31 14:04:39 -0400236 SkPMColor4f color = this->first()->color();
Brian Salomonf86d37b2017-06-16 10:04:34 -0400237 auto result = fHelper.xpRequiresDstTexture(
Brian Osman532b3f92018-07-11 10:02:07 -0400238 caps, clip, GrProcessorAnalysisCoverage::kSingleChannel, &color);
Brian Salomonbaaf4392017-06-15 09:59:23 -0400239 this->first()->setColor(color);
240 return result;
bsalomon08d14152016-06-30 12:45:18 -0700241 }
242
bsalomon08d14152016-06-30 12:45:18 -0700243private:
Brian Salomon91326c32017-08-09 16:02:19 -0400244 void onPrepareDraws(Target* target) override {
bsalomon4be9a302016-07-06 07:03:26 -0700245 using namespace GrDefaultGeoProcFactory;
246
Brian Salomon3de0aee2017-01-29 09:34:17 -0500247 Color color(Color::kPremulGrColorAttribute_Type);
Brian Salomon92be2f72018-06-19 14:33:47 -0400248 Coverage::Type coverageType = Coverage::kSolid_Type;
249 if (!fHelper.compatibleWithAlphaAsCoverage()) {
250 coverageType = Coverage::kAttribute_Type;
Brian Salomon92be2f72018-06-19 14:33:47 -0400251 }
252 LocalCoords lc = LocalCoords::kUnused_Type;
253 if (fHelper.usesLocalCoords()) {
254 lc = LocalCoords::kHasExplicit_Type;
Brian Salomon92be2f72018-06-19 14:33:47 -0400255 }
256
Brian Salomon6a639042016-12-14 11:08:17 -0500257 sk_sp<GrGeometryProcessor> gp =
Ruiqi Maob609e6d2018-07-17 10:19:38 -0400258 GrDefaultGeoProcFactory::Make(target->caps().shaderCaps(), color, coverageType,
259 lc, SkMatrix::I());
bsalomon08d14152016-06-30 12:45:18 -0700260 if (!gp) {
261 SkDebugf("Couldn't create GrGeometryProcessor\n");
262 return;
263 }
264
Brian Osmanf04fb3c2018-11-12 15:34:00 -0500265 size_t vertexStride = gp->vertexStride();
bsalomon08d14152016-06-30 12:45:18 -0700266
Brian Salomond28a79d2017-10-16 13:01:07 -0400267 sk_sp<const GrBuffer> indexBuffer = get_index_buffer(target->resourceProvider());
Brian Salomon7eae3e02018-08-07 14:02:38 +0000268 PatternHelper helper(target, GrPrimitiveType::kTriangles, vertexStride, indexBuffer.get(),
269 kVertsPerAAFillRect, kIndicesPerAAFillRect, fRectCnt);
270 void* vertices = helper.vertices();
bsalomon08d14152016-06-30 12:45:18 -0700271 if (!vertices || !indexBuffer) {
272 SkDebugf("Could not allocate vertices\n");
273 return;
274 }
275
bsalomon4be9a302016-07-06 07:03:26 -0700276 const RectInfo* info = this->first();
277 const SkMatrix* localMatrix = nullptr;
278 for (int i = 0; i < fRectCnt; i++) {
Brian Salomon6a639042016-12-14 11:08:17 -0500279 intptr_t verts =
280 reinterpret_cast<intptr_t>(vertices) + i * kVertsPerAAFillRect * vertexStride;
Brian Salomonbaaf4392017-06-15 09:59:23 -0400281 if (fHelper.usesLocalCoords()) {
bsalomon4be9a302016-07-06 07:03:26 -0700282 if (info->hasLocalMatrix()) {
283 localMatrix = &static_cast<const RectWithLocalMatrixInfo*>(info)->localMatrix();
284 } else {
285 localMatrix = &SkMatrix::I();
286 }
287 }
Brian Osman1be2b7c2018-10-29 16:07:15 -0400288 // TODO4F: Preserve float colors
Brian Osmancf860852018-10-31 14:04:39 -0400289 generate_aa_fill_rect_geometry(verts, vertexStride, info->color().toBytes_RGBA(),
Brian Osman1be2b7c2018-10-29 16:07:15 -0400290 info->viewMatrix(), info->rect(), info->devRect(),
Brian Salomonbaaf4392017-06-15 09:59:23 -0400291 fHelper.compatibleWithAlphaAsCoverage(), localMatrix);
bsalomon4be9a302016-07-06 07:03:26 -0700292 info = this->next(info);
bsalomon08d14152016-06-30 12:45:18 -0700293 }
Brian Salomon49348902018-06-26 09:12:38 -0400294 auto pipe = fHelper.makePipeline(target);
Brian Salomon7eae3e02018-08-07 14:02:38 +0000295 helper.recordDraw(target, std::move(gp), pipe.fPipeline, pipe.fFixedDynamicState);
bsalomon08d14152016-06-30 12:45:18 -0700296 }
297
Brian Salomon7eae3e02018-08-07 14:02:38 +0000298 CombineResult onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
Brian Salomon6a639042016-12-14 11:08:17 -0500299 AAFillRectOp* that = t->cast<AAFillRectOp>();
Brian Salomonbaaf4392017-06-15 09:59:23 -0400300 if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) {
Brian Salomon7eae3e02018-08-07 14:02:38 +0000301 return CombineResult::kCannotCombine;
benjaminwagnerd87a6b22016-07-04 11:30:01 -0700302 }
303
bsalomon4be9a302016-07-06 07:03:26 -0700304 fRectData.push_back_n(that->fRectData.count(), that->fRectData.begin());
305 fRectCnt += that->fRectCnt;
Brian Salomon7eae3e02018-08-07 14:02:38 +0000306 return CombineResult::kMerged;
benjaminwagnerd87a6b22016-07-04 11:30:01 -0700307 }
308
309 struct RectInfo {
bsalomon4be9a302016-07-06 07:03:26 -0700310 public:
Brian Osmancf860852018-10-31 14:04:39 -0400311 RectInfo(const SkPMColor4f& color, const SkMatrix& viewMatrix, const SkRect& rect,
bsalomon4be9a302016-07-06 07:03:26 -0700312 const SkRect& devRect)
Brian Salomon6a639042016-12-14 11:08:17 -0500313 : RectInfo(color, viewMatrix, rect, devRect, HasLocalMatrix::kNo) {}
bsalomon4be9a302016-07-06 07:03:26 -0700314 bool hasLocalMatrix() const { return HasLocalMatrix::kYes == fHasLocalMatrix; }
Brian Osmancf860852018-10-31 14:04:39 -0400315 const SkPMColor4f& color() const { return fColor; }
bsalomon4be9a302016-07-06 07:03:26 -0700316 const SkMatrix& viewMatrix() const { return fViewMatrix; }
317 const SkRect& rect() const { return fRect; }
318 const SkRect& devRect() const { return fDevRect; }
319
Brian Osmancf860852018-10-31 14:04:39 -0400320 void setColor(const SkPMColor4f& color) { fColor = color; }
Brian Salomon6a639042016-12-14 11:08:17 -0500321
bsalomon4be9a302016-07-06 07:03:26 -0700322 protected:
323 enum class HasLocalMatrix : uint32_t { kNo, kYes };
324
Brian Osmancf860852018-10-31 14:04:39 -0400325 RectInfo(const SkPMColor4f& color, const SkMatrix& viewMatrix, const SkRect& rect,
bsalomon4be9a302016-07-06 07:03:26 -0700326 const SkRect& devRect, HasLocalMatrix hasLM)
327 : fHasLocalMatrix(hasLM)
328 , fColor(color)
329 , fViewMatrix(viewMatrix)
330 , fRect(rect)
331 , fDevRect(devRect) {}
332
333 HasLocalMatrix fHasLocalMatrix;
Brian Osmancf860852018-10-31 14:04:39 -0400334 SkPMColor4f fColor;
benjaminwagnerd87a6b22016-07-04 11:30:01 -0700335 SkMatrix fViewMatrix;
336 SkRect fRect;
337 SkRect fDevRect;
338 };
339
bsalomon4be9a302016-07-06 07:03:26 -0700340 struct RectWithLocalMatrixInfo : public RectInfo {
341 public:
Brian Osmancf860852018-10-31 14:04:39 -0400342 RectWithLocalMatrixInfo(const SkPMColor4f& color, const SkMatrix& viewMatrix,
Brian Osman936fe7d2018-10-30 15:30:35 -0400343 const SkRect& rect, const SkRect& devRect,
344 const SkMatrix& localMatrix)
Brian Salomon6a639042016-12-14 11:08:17 -0500345 : RectInfo(color, viewMatrix, rect, devRect, HasLocalMatrix::kYes)
346 , fLocalMatrix(localMatrix) {}
bsalomon4be9a302016-07-06 07:03:26 -0700347 const SkMatrix& localMatrix() const { return fLocalMatrix; }
Brian Salomon6a639042016-12-14 11:08:17 -0500348
bsalomon4be9a302016-07-06 07:03:26 -0700349 private:
benjaminwagnerd87a6b22016-07-04 11:30:01 -0700350 SkMatrix fLocalMatrix;
bsalomon0fdec8a2016-07-01 06:31:25 -0700351 };
352
bsalomon4be9a302016-07-06 07:03:26 -0700353 RectInfo* first() { return reinterpret_cast<RectInfo*>(fRectData.begin()); }
354 const RectInfo* first() const { return reinterpret_cast<const RectInfo*>(fRectData.begin()); }
355 const RectInfo* next(const RectInfo* prev) const {
Brian Salomon6a639042016-12-14 11:08:17 -0500356 intptr_t next =
357 reinterpret_cast<intptr_t>(prev) +
358 (prev->hasLocalMatrix() ? sizeof(RectWithLocalMatrixInfo) : sizeof(RectInfo));
bsalomon4be9a302016-07-06 07:03:26 -0700359 return reinterpret_cast<const RectInfo*>(next);
360 }
361
bsalomon4be9a302016-07-06 07:03:26 -0700362 SkSTArray<4 * sizeof(RectWithLocalMatrixInfo), uint8_t, true> fRectData;
Brian Salomonbaaf4392017-06-15 09:59:23 -0400363 Helper fHelper;
bsalomon4be9a302016-07-06 07:03:26 -0700364 int fRectCnt;
bsalomon08d14152016-06-30 12:45:18 -0700365
Brian Salomonbaaf4392017-06-15 09:59:23 -0400366 typedef GrMeshDrawOp INHERITED;
joshualitt147dc062015-08-12 11:51:46 -0700367};
368
Brian Salomonbaaf4392017-06-15 09:59:23 -0400369} // anonymous namespace
joshualitt9ff64252015-08-10 09:03:51 -0700370
Brian Salomonbaaf4392017-06-15 09:59:23 -0400371namespace GrRectOpFactory {
joshualitt147dc062015-08-12 11:51:46 -0700372
Robert Phillips7c525e62018-06-12 10:11:12 -0400373std::unique_ptr<GrDrawOp> MakeAAFill(GrContext* context,
374 GrPaint&& paint,
375 const SkMatrix& viewMatrix,
376 const SkRect& rect,
377 const GrUserStencilSettings* stencil) {
Brian Salomonbaaf4392017-06-15 09:59:23 -0400378 if (!view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
379 return nullptr;
380 }
bsalomonc55271f2015-11-09 11:55:57 -0800381 SkRect devRect;
382 viewMatrix.mapRect(&devRect, rect);
Robert Phillips7c525e62018-06-12 10:11:12 -0400383 return AAFillRectOp::Make(context, std::move(paint), viewMatrix, rect, devRect,
384 nullptr, stencil);
bsalomonc55271f2015-11-09 11:55:57 -0800385}
386
Robert Phillips7c525e62018-06-12 10:11:12 -0400387std::unique_ptr<GrDrawOp> MakeAAFillWithLocalMatrix(GrContext* context,
388 GrPaint&& paint,
389 const SkMatrix& viewMatrix,
Brian Salomonbaaf4392017-06-15 09:59:23 -0400390 const SkMatrix& localMatrix,
391 const SkRect& rect) {
392 if (!view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
393 return nullptr;
394 }
395 SkRect devRect;
396 viewMatrix.mapRect(&devRect, rect);
Robert Phillips7c525e62018-06-12 10:11:12 -0400397 return AAFillRectOp::Make(context, std::move(paint), viewMatrix, rect, devRect,
398 &localMatrix, nullptr);
Brian Salomonbaaf4392017-06-15 09:59:23 -0400399}
400
Robert Phillips7c525e62018-06-12 10:11:12 -0400401std::unique_ptr<GrDrawOp> MakeAAFillWithLocalRect(GrContext* context,
402 GrPaint&& paint,
403 const SkMatrix& viewMatrix,
404 const SkRect& rect,
405 const SkRect& localRect) {
Brian Salomonbaaf4392017-06-15 09:59:23 -0400406 if (!view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
407 return nullptr;
408 }
bsalomonc55271f2015-11-09 11:55:57 -0800409 SkRect devRect;
410 viewMatrix.mapRect(&devRect, rect);
411 SkMatrix localMatrix;
412 if (!localMatrix.setRectToRect(rect, localRect, SkMatrix::kFill_ScaleToFit)) {
413 return nullptr;
414 }
Robert Phillips7c525e62018-06-12 10:11:12 -0400415 return AAFillRectOp::Make(context, std::move(paint), viewMatrix, rect, devRect,
416 &localMatrix, nullptr);
bsalomonc55271f2015-11-09 11:55:57 -0800417}
Brian Salomonbaaf4392017-06-15 09:59:23 -0400418
419} // namespace GrRectOpFactory
joshualitt37eb1842015-08-12 06:36:57 -0700420
joshualitt9ff64252015-08-10 09:03:51 -0700421///////////////////////////////////////////////////////////////////////////////////////////////////
422
Hal Canary6f6961e2017-01-31 13:50:44 -0500423#if GR_TEST_UTILS
joshualitt9ff64252015-08-10 09:03:51 -0700424
Brian Salomon5ec9def2016-12-20 15:34:05 -0500425#include "GrDrawOpTest.h"
joshualitt9ff64252015-08-10 09:03:51 -0700426
Brian Salomonbaaf4392017-06-15 09:59:23 -0400427GR_DRAW_OP_TEST_DEFINE(AAFillRectOp) {
428 SkMatrix viewMatrix;
429 do {
430 viewMatrix = GrTest::TestMatrixInvertible(random);
431 } while (!view_matrix_ok_for_aa_fill_rect(viewMatrix));
joshualitt090ae8e2015-08-14 09:01:21 -0700432 SkRect rect = GrTest::TestRect(random);
Brian Salomonbaaf4392017-06-15 09:59:23 -0400433 SkRect devRect;
434 viewMatrix.mapRect(&devRect, rect);
435 const SkMatrix* localMatrix = nullptr;
436 SkMatrix m;
437 if (random->nextBool()) {
438 m = GrTest::TestMatrix(random);
439 }
Robert Phillips7c525e62018-06-12 10:11:12 -0400440 const GrUserStencilSettings* stencil = random->nextBool() ? nullptr
441 : GrGetRandomStencil(random, context);
442 return AAFillRectOp::Make(context, std::move(paint), viewMatrix, rect,
443 devRect, localMatrix, stencil);
joshualitt9ff64252015-08-10 09:03:51 -0700444}
445
446#endif