Flutter Engine
The Flutter Engine
LatticeOp.cpp
Go to the documentation of this file.
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
9
11#include "include/core/SkRect.h"
15#include "src/gpu/KeyBuilder.h"
22#include "src/gpu/ganesh/SkGr.h"
28
29using namespace skia_private;
30
32
33namespace {
34
35class LatticeGP : public GrGeometryProcessor {
36public:
38 const GrSurfaceProxyView& view,
41 bool wideColor) {
42 return arena->make([&](void* ptr) {
43 return new (ptr) LatticeGP(view, std::move(csxf), filter, wideColor);
44 });
45 }
46
47 const char* name() const override { return "LatticeGP"; }
48
49 void addToKey(const GrShaderCaps&, KeyBuilder* b) const override {
50 b->add32(GrColorSpaceXform::XformKey(fColorSpaceXform.get()));
51 }
52
53 std::unique_ptr<ProgramImpl> makeProgramImpl(const GrShaderCaps&) const override {
54 class Impl : public ProgramImpl {
55 public:
56 void setData(const GrGLSLProgramDataManager& pdman,
57 const GrShaderCaps&,
58 const GrGeometryProcessor& geomProc) override {
59 const auto& latticeGP = geomProc.cast<LatticeGP>();
60 fColorSpaceXformHelper.setData(pdman, latticeGP.fColorSpaceXform.get());
61 }
62
63 private:
64 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
65 using Interpolation = GrGLSLVaryingHandler::Interpolation;
66 const auto& latticeGP = args.fGeomProc.cast<LatticeGP>();
67 fColorSpaceXformHelper.emitCode(args.fUniformHandler,
68 latticeGP.fColorSpaceXform.get());
69
70 args.fVaryingHandler->emitAttributes(latticeGP);
71 WriteOutputPosition(args.fVertBuilder, gpArgs, latticeGP.fInPosition.name());
72 gpArgs->fLocalCoordVar = latticeGP.fInTextureCoords.asShaderVar();
73
74 args.fFragBuilder->codeAppend("float2 textureCoords;");
75 args.fVaryingHandler->addPassThroughAttribute(
76 latticeGP.fInTextureCoords.asShaderVar(),
77 "textureCoords");
78 args.fFragBuilder->codeAppend("float4 textureDomain;");
79 args.fVaryingHandler->addPassThroughAttribute(
80 latticeGP.fInTextureDomain.asShaderVar(),
81 "textureDomain",
82 Interpolation::kCanBeFlat);
83 args.fFragBuilder->codeAppendf("half4 %s;", args.fOutputColor);
84 args.fVaryingHandler->addPassThroughAttribute(latticeGP.fInColor.asShaderVar(),
85 args.fOutputColor,
86 Interpolation::kCanBeFlat);
87 args.fFragBuilder->codeAppendf("%s = ", args.fOutputColor);
88 args.fFragBuilder->appendTextureLookupAndBlend(
89 args.fOutputColor,
91 args.fTexSamplers[0],
92 "clamp(textureCoords, textureDomain.xy, textureDomain.zw)",
93 &fColorSpaceXformHelper);
94 args.fFragBuilder->codeAppend(";");
95 args.fFragBuilder->codeAppendf("const half4 %s = half4(1);", args.fOutputCoverage);
96 }
97
98 GrGLSLColorSpaceXformHelper fColorSpaceXformHelper;
99 };
100
101 return std::make_unique<Impl>();
102 }
103
104private:
105 LatticeGP(const GrSurfaceProxyView& view, sk_sp<GrColorSpaceXform> csxf,
106 GrSamplerState::Filter filter, bool wideColor)
107 : INHERITED(kLatticeGP_ClassID)
108 , fColorSpaceXform(std::move(csxf)) {
109
110 fSampler.reset(GrSamplerState(GrSamplerState::WrapMode::kClamp, filter),
111 view.proxy()->backendFormat(), view.swizzle());
112 this->setTextureSamplerCnt(1);
113 fInPosition = {"position", kFloat2_GrVertexAttribType, SkSLType::kFloat2};
114 fInTextureCoords = {"textureCoords", kFloat2_GrVertexAttribType, SkSLType::kFloat2};
115 fInTextureDomain = {"textureDomain", kFloat4_GrVertexAttribType, SkSLType::kFloat4};
116 fInColor = MakeColorAttribute("color", wideColor);
117 this->setVertexAttributesWithImplicitOffsets(&fInPosition, 4);
118 }
119
120 const TextureSampler& onTextureSampler(int) const override { return fSampler; }
121
122 Attribute fInPosition;
123 Attribute fInTextureCoords;
124 Attribute fInTextureDomain;
125 Attribute fInColor;
126
127 sk_sp<GrColorSpaceXform> fColorSpaceXform;
128 TextureSampler fSampler;
129
131};
132
133class NonAALatticeOp final : public GrMeshDrawOp {
134private:
136
137public:
139
140 static GrOp::Owner Make(GrRecordingContext* context,
141 GrPaint&& paint,
142 const SkMatrix& viewMatrix,
144 SkAlphaType alphaType,
145 sk_sp<GrColorSpaceXform> colorSpaceXForm,
147 std::unique_ptr<SkLatticeIter> iter,
148 const SkRect& dst) {
149 SkASSERT(view.proxy());
150 return Helper::FactoryHelper<NonAALatticeOp>(context, std::move(paint), viewMatrix,
151 std::move(view), alphaType,
152 std::move(colorSpaceXForm), filter,
153 std::move(iter), dst);
154 }
155
156 NonAALatticeOp(GrProcessorSet* processorSet, const SkPMColor4f& color,
157 const SkMatrix& viewMatrix, GrSurfaceProxyView view,
158 SkAlphaType alphaType, sk_sp<GrColorSpaceXform> colorSpaceXform,
159 GrSamplerState::Filter filter, std::unique_ptr<SkLatticeIter> iter,
160 const SkRect& dst)
161 : INHERITED(ClassID())
162 , fHelper(processorSet, GrAAType::kNone)
163 , fView(std::move(view))
164 , fAlphaType(alphaType)
165 , fColorSpaceXform(std::move(colorSpaceXform))
166 , fFilter(filter) {
167 Patch& patch = fPatches.push_back();
168 patch.fViewMatrix = viewMatrix;
169 patch.fColor = color;
170 patch.fIter = std::move(iter);
171 patch.fDst = dst;
172
173 // setup bounds
174 this->setTransformedBounds(patch.fDst, viewMatrix, HasAABloat::kNo, IsHairline::kNo);
175 }
176
177 const char* name() const override { return "NonAALatticeOp"; }
178
179 void visitProxies(const GrVisitProxyFunc& func) const override {
180 func(fView.proxy(), skgpu::Mipmapped::kNo);
181 if (fProgramInfo) {
182 fProgramInfo->visitFPProxies(func);
183 } else {
184 fHelper.visitProxies(func);
185 }
186 }
187
188 FixedFunctionFlags fixedFunctionFlags() const override { return fHelper.fixedFunctionFlags(); }
189
190 GrProcessorSet::Analysis finalize(const GrCaps& caps, const GrAppliedClip* clip,
191 GrClampType clampType) override {
192 auto opaque = fPatches[0].fColor.isOpaque() && fAlphaType == kOpaque_SkAlphaType
195 auto analysisColor = GrProcessorAnalysisColor(opaque);
196 auto result = fHelper.finalizeProcessors(caps, clip, clampType,
198 &analysisColor);
199 analysisColor.isConstant(&fPatches[0].fColor);
200 fWideColor = !fPatches[0].fColor.fitsInBytes();
201 return result;
202 }
203
204private:
205 GrProgramInfo* programInfo() override { return fProgramInfo; }
206
207 void onCreateProgramInfo(const GrCaps* caps,
208 SkArenaAlloc* arena,
209 const GrSurfaceProxyView& writeView,
210 bool usesMSAASurface,
211 GrAppliedClip&& appliedClip,
212 const GrDstProxyView& dstProxyView,
213 GrXferBarrierFlags renderPassXferBarriers,
214 GrLoadOp colorLoadOp) override {
215
216 auto gp = LatticeGP::Make(arena, fView, fColorSpaceXform, fFilter, fWideColor);
217 if (!gp) {
218 return;
219 }
220
221 fProgramInfo = GrSimpleMeshDrawOpHelper::CreateProgramInfo(caps, arena, writeView,
222 usesMSAASurface,
223 std::move(appliedClip),
224 dstProxyView, gp,
225 fHelper.detachProcessorSet(),
227 renderPassXferBarriers,
228 colorLoadOp,
229 fHelper.pipelineFlags(),
231 }
232
233 void onPrepareDraws(GrMeshDrawTarget* target) override {
234 if (!fProgramInfo) {
235 this->createProgramInfo(target);
236 if (!fProgramInfo) {
237 return;
238 }
239 }
240
241 int patchCnt = fPatches.size();
242 int numRects = 0;
243 for (int i = 0; i < patchCnt; i++) {
244 numRects += fPatches[i].fIter->numRectsToDraw();
245 }
246
247 if (!numRects) {
248 return;
249 }
250
251 const size_t kVertexStride = fProgramInfo->geomProc().vertexStride();
252
253 QuadHelper helper(target, kVertexStride, numRects);
254
255 VertexWriter vertices{helper.vertices()};
256 if (!vertices) {
257 SkDebugf("Could not allocate vertices\n");
258 return;
259 }
260
261 for (int i = 0; i < patchCnt; i++) {
262 const Patch& patch = fPatches[i];
263
264 VertexColor patchColor(patch.fColor, fWideColor);
265
266 // Apply the view matrix here if it is scale-translate. Otherwise, we need to
267 // wait until we've created the dst rects.
268 bool isScaleTranslate = patch.fViewMatrix.isScaleTranslate();
269 if (isScaleTranslate) {
270 patch.fIter->mapDstScaleTranslate(patch.fViewMatrix);
271 }
272
273 SkIRect srcR;
274 SkRect dstR;
275 skvx::float4 scales(1.f / fView.proxy()->width(), 1.f / fView.proxy()->height(),
276 1.f / fView.proxy()->width(), 1.f / fView.proxy()->height());
277 static const skvx::float4 kDomainOffsets(0.5f, 0.5f, -0.5f, -0.5f);
278 static const skvx::float4 kFlipOffsets(0.f, 1.f, 0.f, 1.f);
279 static const skvx::float4 kFlipMuls(1.f, -1.f, 1.f, -1.f);
280 while (patch.fIter->next(&srcR, &dstR)) {
283 skvx::float4 domain = coords + kDomainOffsets;
284 coords *= scales;
285 domain *= scales;
286 if (fView.origin() == kBottomLeft_GrSurfaceOrigin) {
287 coords = kFlipMuls * coords + kFlipOffsets;
288 domain = skvx::shuffle<0, 3, 2, 1>(kFlipMuls * domain + kFlipOffsets);
289 }
290 SkRect texDomain;
291 SkRect texCoords;
292 domain.store(&texDomain);
293 coords.store(&texCoords);
294
295 if (isScaleTranslate) {
296 vertices.writeQuad(VertexWriter::TriStripFromRect(dstR),
298 texDomain,
299 patchColor);
300 } else {
301 SkPoint mappedPts[4];
302 patch.fViewMatrix.mapRectToQuad(mappedPts, dstR);
303 // In the above if statement, writeQuad writes the corners as:
304 // left-top, left-bottom, right-top, right-bottom.
305 // However, mapRectToQuad returns them in the order:
306 // left-top, right-top, right-bottom, left-bottom
307 // Thus we write out the vertices to match the writeQuad path.
308 vertices << mappedPts[0]
309 << SkPoint::Make(texCoords.fLeft, texCoords.fTop)
310 << texDomain
311 << patchColor;
312 vertices << mappedPts[3]
313 << SkPoint::Make(texCoords.fLeft, texCoords.fBottom)
314 << texDomain
315 << patchColor;
316 vertices << mappedPts[1]
317 << SkPoint::Make(texCoords.fRight, texCoords.fTop)
318 << texDomain
319 << patchColor;
320 vertices << mappedPts[2]
321 << SkPoint::Make(texCoords.fRight, texCoords.fBottom)
322 << texDomain
323 << patchColor;
324 }
325 }
326 }
327
328 fMesh = helper.mesh();
329 }
330
331 void onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) override {
332 if (!fProgramInfo || !fMesh) {
333 return;
334 }
335
336 flushState->bindPipelineAndScissorClip(*fProgramInfo, chainBounds);
337 flushState->bindTextures(fProgramInfo->geomProc(),
338 *fView.proxy(),
339 fProgramInfo->pipeline());
340 flushState->drawMesh(*fMesh);
341 }
342
343 CombineResult onCombineIfPossible(GrOp* t, SkArenaAlloc*, const GrCaps& caps) override {
344 NonAALatticeOp* that = t->cast<NonAALatticeOp>();
345 if (fView != that->fView) {
346 return CombineResult::kCannotCombine;
347 }
348 if (fFilter != that->fFilter) {
349 return CombineResult::kCannotCombine;
350 }
351 if (GrColorSpaceXform::Equals(fColorSpaceXform.get(), that->fColorSpaceXform.get())) {
352 return CombineResult::kCannotCombine;
353 }
354 if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) {
355 return CombineResult::kCannotCombine;
356 }
357
358 fPatches.move_back_n(that->fPatches.size(), that->fPatches.begin());
359 fWideColor |= that->fWideColor;
360 return CombineResult::kMerged;
361 }
362
363#if defined(GR_TEST_UTILS)
364 SkString onDumpInfo() const override {
365 SkString str;
366
367 for (int i = 0; i < fPatches.size(); ++i) {
368 str.appendf("%d: Color: 0x%08x Dst [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n", i,
369 fPatches[i].fColor.toBytes_RGBA(), fPatches[i].fDst.fLeft,
370 fPatches[i].fDst.fTop, fPatches[i].fDst.fRight, fPatches[i].fDst.fBottom);
371 }
372
373 str += fHelper.dumpInfo();
374 return str;
375 }
376#endif
377
378 struct Patch {
380 std::unique_ptr<SkLatticeIter> fIter;
383 };
384
385 Helper fHelper;
387 GrSurfaceProxyView fView;
389 sk_sp<GrColorSpaceXform> fColorSpaceXform;
391 bool fWideColor;
392
393 GrSimpleMesh* fMesh = nullptr;
394 GrProgramInfo* fProgramInfo = nullptr;
395
396 using INHERITED = GrMeshDrawOp;
397};
398
399} // anonymous namespace
400
402 GrPaint&& paint,
403 const SkMatrix& viewMatrix,
405 SkAlphaType alphaType,
406 sk_sp<GrColorSpaceXform> colorSpaceXform,
408 std::unique_ptr<SkLatticeIter> iter,
409 const SkRect& dst) {
410 return NonAALatticeOp::Make(context, std::move(paint), viewMatrix, std::move(view), alphaType,
411 std::move(colorSpaceXform), filter, std::move(iter), dst);
412}
413
414} // namespace skgpu::ganesh::LatticeOp
415
416#if defined(GR_TEST_UTILS)
420
421/** Randomly divides subset into count divs. */
422static void init_random_divs(int divs[], int count, int subsetStart, int subsetStop,
423 SkRandom* random) {
424 // Rules for lattice divs: Must be strictly increasing and in the range
425 // [subsetStart, subsetStop.
426 // Not terribly efficient alg for generating random divs:
427 // 1 Start with minimum legal pixels between each div.
428 // 2) Randomly assign the remaining pixels of the subset to divs.
429 // 3) Convert from pixel counts to div offsets.
430
431 // 1) Initially each divs[i] represents the number of pixels between
432 // div i-1 and i. The initial div is allowed to be at subsetStart. There
433 // must be one pixel spacing between subsequent divs.
434 divs[0] = 0;
435 for (int i = 1; i < count; ++i) {
436 divs[i] = 1;
437 }
438 // 2) Assign the remaining subset pixels to fall
439 int subsetLength = subsetStop - subsetStart;
440 for (int i = 0; i < subsetLength - count; ++i) {
441 // +1 because count divs means count+1 intervals.
442 int entry = random->nextULessThan(count + 1);
443 // We don't have an entry to to store the count after the last div
444 if (entry < count) {
445 divs[entry]++;
446 }
447 }
448 // 3) Now convert the counts between divs to pixel indices, incorporating the subset's offset.
449 int offset = subsetStart;
450 for (int i = 0; i < count; ++i) {
451 divs[i] += offset;
452 offset = divs[i];
453 }
454}
455
456GR_DRAW_OP_TEST_DEFINE(NonAALatticeOp) {
457 SkCanvas::Lattice lattice;
458 // We loop because our random lattice code can produce an invalid lattice in the case where
459 // there is a single div separator in both x and y and both are aligned with the left and top
460 // edge of the image subset, respectively.
461 std::unique_ptr<int[]> xdivs;
462 std::unique_ptr<int[]> ydivs;
463 std::unique_ptr<SkCanvas::Lattice::RectType[]> flags;
464 std::unique_ptr<SkColor[]> colors;
465 SkIRect subset;
466 SkISize dims;
467 dims.fWidth = random->nextRangeU(1, 1000);
468 dims.fHeight = random->nextRangeU(1, 1000);
471 const GrBackendFormat format =
472 context->priv().caps()->getDefaultBackendFormat(GrColorType::kRGBA_8888,
474
475 auto proxy = context->priv().proxyProvider()->createProxy(format,
476 dims,
478 1,
483 /*label=*/"LatticeOp");
484
485 do {
486 if (random->nextBool()) {
487 subset.fLeft = random->nextULessThan(dims.fWidth);
488 subset.fRight = random->nextRangeU(subset.fLeft + 1, dims.fWidth);
489 subset.fTop = random->nextULessThan(dims.fHeight);
490 subset.fBottom = random->nextRangeU(subset.fTop + 1, dims.fHeight);
491 } else {
492 subset.setXYWH(0, 0, dims.fWidth, dims.fHeight);
493 }
494 // SkCanvas::Lattice allows bounds to be null. However, SkCanvas creates a temp Lattice with
495 // a non-null bounds before creating a SkLatticeIter since SkLatticeIter requires a bounds.
496 lattice.fBounds = &subset;
497 lattice.fXCount = random->nextRangeU(1, subset.width());
498 lattice.fYCount = random->nextRangeU(1, subset.height());
499 xdivs.reset(new int[lattice.fXCount]);
500 ydivs.reset(new int[lattice.fYCount]);
501 init_random_divs(xdivs.get(), lattice.fXCount, subset.fLeft, subset.fRight, random);
502 init_random_divs(ydivs.get(), lattice.fYCount, subset.fTop, subset.fBottom, random);
503 lattice.fXDivs = xdivs.get();
504 lattice.fYDivs = ydivs.get();
505 bool hasFlags = random->nextBool();
506 if (hasFlags) {
507 int n = (lattice.fXCount + 1) * (lattice.fYCount + 1);
509 colors.reset(new SkColor[n]);
510 for (int i = 0; i < n; ++i) {
513 }
514 lattice.fRectTypes = flags.get();
515 lattice.fColors = colors.get();
516 } else {
517 lattice.fRectTypes = nullptr;
518 lattice.fColors = nullptr;
519 }
520 } while (!SkLatticeIter::Valid(dims.fWidth, dims.fHeight, lattice));
521 SkRect dst;
522 dst.fLeft = random->nextRangeScalar(-2000.5f, 1000.f);
523 dst.fTop = random->nextRangeScalar(-2000.5f, 1000.f);
524 dst.fRight = dst.fLeft + random->nextRangeScalar(0.5f, 1000.f);
525 dst.fBottom = dst.fTop + random->nextRangeScalar(0.5f, 1000.f);
526 std::unique_ptr<SkLatticeIter> iter(new SkLatticeIter(lattice, dst));
527 SkMatrix viewMatrix = GrTest::TestMatrixPreservesRightAngles(random);
528 auto csxf = GrTest::TestColorXform(random);
531
533 std::move(proxy), origin,
534 context->priv().caps()->getReadSwizzle(format, GrColorType::kRGBA_8888));
535
537 std::move(paint),
538 viewMatrix,
539 std::move(view),
541 std::move(csxf),
542 filter,
543 std::move(iter),
544 dst);
545}
546
547#endif
int count
Definition: FontMgrTest.cpp:50
#define DEFINE_OP_CLASS_ID
Definition: GrOp.h:64
GrClampType
Definition: GrTypesPriv.h:228
std::function< void(GrSurfaceProxy *, skgpu::Mipmapped)> GrVisitProxyFunc
Definition: GrTypesPriv.h:943
GrLoadOp
Definition: GrTypesPriv.h:155
@ kFloat2_GrVertexAttribType
Definition: GrTypesPriv.h:314
@ kFloat4_GrVertexAttribType
Definition: GrTypesPriv.h:316
GrSurfaceOrigin
Definition: GrTypes.h:147
@ kBottomLeft_GrSurfaceOrigin
Definition: GrTypes.h:149
@ kTopLeft_GrSurfaceOrigin
Definition: GrTypes.h:148
GrXferBarrierFlags
std::unique_ptr< SkLatticeIter > fIter
Definition: LatticeOp.cpp:380
SkMatrix fViewMatrix
Definition: LatticeOp.cpp:379
SkPMColor4f fColor
Definition: LatticeOp.cpp:382
SkRect fDst
Definition: LatticeOp.cpp:381
SkAlphaType fAlphaType
SkAlphaType
Definition: SkAlphaType.h:26
@ kOpaque_SkAlphaType
pixel is opaque
Definition: SkAlphaType.h:28
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
Definition: SkAlphaType.h:29
#define SkASSERT(cond)
Definition: SkAssert.h:116
@ kModulate
r = s*d
uint32_t SkColor
Definition: SkColor.h:37
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
Definition: SkPath.cpp:3892
#define INHERITED(method,...)
Definition: SkRecorder.cpp:128
SkFilterMode
#define SkIntToScalar(x)
Definition: SkScalar.h:57
Definition: GrCaps.h:57
static bool Equals(const GrColorSpaceXform *a, const GrColorSpaceXform *b)
static uint32_t XformKey(const GrColorSpaceXform *xform)
size_t vertexStride() const
void drawMesh(const GrSimpleMesh &mesh)
void bindPipelineAndScissorClip(const GrProgramInfo &programInfo, const SkRect &drawBounds)
void bindTextures(const GrGeometryProcessor &geomProc, const GrSurfaceProxy &singleGeomProcTexture, const GrPipeline &pipeline)
Definition: GrOp.h:70
std::unique_ptr< GrOp > Owner
Definition: GrOp.h:72
const T & cast() const
Definition: GrOp.h:148
const T & cast() const
Definition: GrProcessor.h:127
const GrPipeline & pipeline() const
Definition: GrProgramInfo.h:39
const GrGeometryProcessor & geomProc() const
Definition: GrProgramInfo.h:40
void visitFPProxies(const GrVisitProxyFunc &func) const
Definition: GrProgramInfo.h:64
void visitProxies(const GrVisitProxyFunc &func) const
GrDrawOp::FixedFunctionFlags fixedFunctionFlags() const
GrPipeline::InputFlags pipelineFlags() const
GrProcessorSet::Analysis finalizeProcessors(const GrCaps &caps, const GrAppliedClip *clip, GrClampType clampType, GrProcessorAnalysisCoverage geometryCoverage, GrProcessorAnalysisColor *geometryColor)
static GrProgramInfo * CreateProgramInfo(const GrCaps *, SkArenaAlloc *, const GrPipeline *, const GrSurfaceProxyView &writeView, bool usesMSAASurface, GrGeometryProcessor *, GrPrimitiveType, GrXferBarrierFlags renderPassXferBarriers, GrLoadOp colorLoadOp, const GrUserStencilSettings *=&GrUserStencilSettings::kUnused)
bool isCompatible(const GrSimpleMeshDrawOpHelper &that, const GrCaps &, const SkRect &thisBounds, const SkRect &thatBounds, bool ignoreAAType=false) const
skgpu::Swizzle swizzle() const
GrSurfaceOrigin origin() const
GrSurfaceProxy * proxy() const
const GrBackendFormat & backendFormat() const
int width() const
int height() const
auto make(Ctor &&ctor) -> decltype(ctor(nullptr))
Definition: SkArenaAlloc.h:120
static bool Valid(int imageWidth, int imageHeight, const SkCanvas::Lattice &lattice)
bool nextBool()
Definition: SkRandom.h:117
SkScalar nextRangeScalar(SkScalar min, SkScalar max)
Definition: SkRandom.h:106
uint32_t nextULessThan(uint32_t count)
Definition: SkRandom.h:93
uint32_t nextRangeU(uint32_t min, uint32_t max)
Definition: SkRandom.h:80
void void void appendf(const char format[],...) SK_PRINTF_LIKE(2
Definition: SkString.cpp:550
T * get() const
Definition: SkRefCnt.h:303
const Paint & paint
Definition: color_source.cc:38
DlColor color
static bool b
FlutterSemanticsFlag flags
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
GAsyncResult * result
uint32_t uint32_t * format
uint32_t * target
SK_API sk_sp< SkDocument > Make(SkWStream *dst, const SkSerialProcs *=nullptr, std::function< void(const SkPicture *)> onEndPage=nullptr)
PODArray< SkColor > colors
Definition: SkRecords.h:276
void Helper(uword arg)
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32
dst
Definition: cp.py:12
GrOp::Owner MakeNonAA(GrRecordingContext *context, GrPaint &&paint, const SkMatrix &viewMatrix, GrSurfaceProxyView view, SkAlphaType alphaType, sk_sp< GrColorSpaceXform > colorSpaceXform, GrSamplerState::Filter filter, std::unique_ptr< SkLatticeIter > iter, const SkRect &dst)
Definition: LatticeOp.cpp:401
SeparatedVector2 offset
static const GrUserStencilSettings & kUnused
int fYCount
number of y-coordinates
Definition: SkCanvas.h:1617
const SkIRect * fBounds
source bounds to draw from
Definition: SkCanvas.h:1618
@ kDefault
draws SkBitmap into lattice rectangle
Definition: SkCanvas.h:1608
@ kTransparent
skips lattice rectangle by making it transparent
Definition: SkCanvas.h:1609
const int * fYDivs
y-axis values dividing bitmap
Definition: SkCanvas.h:1614
int fXCount
number of x-coordinates
Definition: SkCanvas.h:1616
const RectType * fRectTypes
array of fill types
Definition: SkCanvas.h:1615
const SkColor * fColors
array of colors
Definition: SkCanvas.h:1619
const int * fXDivs
x-axis values dividing bitmap
Definition: SkCanvas.h:1613
Definition: SkRect.h:32
int32_t fBottom
larger y-axis bounds
Definition: SkRect.h:36
constexpr int32_t height() const
Definition: SkRect.h:165
int32_t fTop
smaller y-axis bounds
Definition: SkRect.h:34
constexpr int32_t width() const
Definition: SkRect.h:158
void setXYWH(int32_t x, int32_t y, int32_t width, int32_t height)
Definition: SkRect.h:268
int32_t fLeft
smaller x-axis bounds
Definition: SkRect.h:33
int32_t fRight
larger x-axis bounds
Definition: SkRect.h:35
Definition: SkSize.h:16
int32_t fHeight
Definition: SkSize.h:18
int32_t fWidth
Definition: SkSize.h:17
static constexpr SkPoint Make(float x, float y)
Definition: SkPoint_impl.h:173
uint32_t toBytes_RGBA() const
SkScalar fBottom
larger y-axis bounds
Definition: extension.cpp:17
SkScalar fLeft
smaller x-axis bounds
Definition: extension.cpp:14
SkScalar fRight
larger x-axis bounds
Definition: extension.cpp:16
SkScalar fTop
smaller y-axis bounds
Definition: extension.cpp:15
static TriStrip< float > TriStripFromRect(const SkRect &r)
Definition: BufferWriter.h:217
Definition: SkVx.h:83
SKVX_ALWAYS_INLINE void store(void *ptr) const
Definition: SkVx.h:112