Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Device_drawTexture.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
14#include "src/core/SkDraw.h"
25#include "src/gpu/ganesh/SkGr.h"
35
36using namespace skia_private;
37
38namespace {
39
40inline bool use_shader(bool textureIsAlphaOnly, const SkPaint& paint) {
41 return textureIsAlphaOnly && paint.getShader();
42}
43
44//////////////////////////////////////////////////////////////////////////////
45// Helper functions for dropping src rect subset with GrSamplerState::Filter::kLinear.
46
47static const SkScalar kColorBleedTolerance = 0.001f;
48
49bool has_aligned_samples(const SkRect& srcRect, const SkRect& transformedRect) {
50 // detect pixel disalignment
51 if (SkScalarAbs(SkScalarRoundToScalar(transformedRect.left()) - transformedRect.left()) < kColorBleedTolerance &&
52 SkScalarAbs(SkScalarRoundToScalar(transformedRect.top()) - transformedRect.top()) < kColorBleedTolerance &&
53 SkScalarAbs(transformedRect.width() - srcRect.width()) < kColorBleedTolerance &&
54 SkScalarAbs(transformedRect.height() - srcRect.height()) < kColorBleedTolerance) {
55 return true;
56 }
57 return false;
58}
59
60bool may_color_bleed(const SkRect& srcRect,
61 const SkRect& transformedRect,
62 const SkMatrix& m,
63 int numSamples) {
64 // Only gets called if has_aligned_samples returned false.
65 // So we can assume that sampling is axis aligned but not texel aligned.
66 SkASSERT(!has_aligned_samples(srcRect, transformedRect));
67 SkRect innerSrcRect(srcRect), innerTransformedRect, outerTransformedRect(transformedRect);
68 if (numSamples > 1) {
69 innerSrcRect.inset(SK_Scalar1, SK_Scalar1);
70 } else {
71 innerSrcRect.inset(SK_ScalarHalf, SK_ScalarHalf);
72 }
73 m.mapRect(&innerTransformedRect, innerSrcRect);
74
75 // The gap between outerTransformedRect and innerTransformedRect
76 // represents the projection of the source border area, which is
77 // problematic for color bleeding. We must check whether any
78 // destination pixels sample the border area.
79 outerTransformedRect.inset(kColorBleedTolerance, kColorBleedTolerance);
80 innerTransformedRect.outset(kColorBleedTolerance, kColorBleedTolerance);
81 SkIRect outer, inner;
82 outerTransformedRect.round(&outer);
83 innerTransformedRect.round(&inner);
84 // If the inner and outer rects round to the same result, it means the
85 // border does not overlap any pixel centers. Yay!
86 return inner != outer;
87}
88
89bool can_ignore_linear_filtering_subset(const SkRect& srcSubset,
90 const SkMatrix& srcRectToDeviceSpace,
91 int numSamples) {
92 if (srcRectToDeviceSpace.rectStaysRect()) {
93 // sampling is axis-aligned
94 SkRect transformedRect;
95 srcRectToDeviceSpace.mapRect(&transformedRect, srcSubset);
96
97 if (has_aligned_samples(srcSubset, transformedRect) ||
98 !may_color_bleed(srcSubset, transformedRect, srcRectToDeviceSpace, numSamples)) {
99 return true;
100 }
101 }
102 return false;
103}
104
105//////////////////////////////////////////////////////////////////////////////
106// Helper functions for drawing an image with ganesh::SurfaceDrawContext
107
108/**
109 * Checks whether the paint is compatible with using SurfaceDrawContext::drawTexture. It is more
110 * efficient than the SkImage general case.
111 */
112bool can_use_draw_texture(const SkPaint& paint, const SkSamplingOptions& sampling) {
113 return (!paint.getColorFilter() && !paint.getShader() && !paint.getMaskFilter() &&
114 !paint.getImageFilter() && !paint.getBlender() && !sampling.isAniso() &&
116}
117
118SkPMColor4f texture_color(SkColor4f paintColor, float entryAlpha, GrColorType srcColorType,
119 const GrColorInfo& dstColorInfo) {
120 paintColor.fA *= entryAlpha;
121 if (GrColorTypeIsAlphaOnly(srcColorType)) {
122 return SkColor4fPrepForDst(paintColor, dstColorInfo).premul();
123 } else {
124 float paintAlpha = SkTPin(paintColor.fA, 0.f, 1.f);
125 return { paintAlpha, paintAlpha, paintAlpha, paintAlpha };
126 }
127}
128
129// Assumes srcRect and dstRect have already been optimized to fit the proxy
131 const GrClip* clip,
132 const SkMatrix& ctm,
133 const SkPaint& paint,
135 const SkRect& srcRect,
136 const SkRect& dstRect,
137 const SkPoint dstClip[4],
138 GrQuadAAFlags aaFlags,
141 const GrColorInfo& srcColorInfo) {
142 if (GrColorTypeIsAlphaOnly(srcColorInfo.colorType())) {
143 view.concatSwizzle(skgpu::Swizzle("aaaa"));
144 }
145 const GrColorInfo& dstInfo = sdc->colorInfo();
146 auto textureXform = GrColorSpaceXform::Make(srcColorInfo, sdc->colorInfo());
147 GrSurfaceProxy* proxy = view.proxy();
148 // Must specify the strict constraint when the proxy is not functionally exact and the src
149 // rect would access pixels outside the proxy's content area without the constraint.
150 if (constraint != SkCanvas::kStrict_SrcRectConstraint && !proxy->isFunctionallyExact()) {
151 // Conservative estimate of how much a coord could be outset from src rect:
152 // 1/2 pixel for AA and 1/2 pixel for linear filtering
153 float buffer = 0.5f * (aaFlags != GrQuadAAFlags::kNone) +
154 GrTextureEffect::kLinearInset * (filter == GrSamplerState::Filter::kLinear);
155 SkRect safeBounds = proxy->getBoundsRect();
156 safeBounds.inset(buffer, buffer);
157 if (!safeBounds.contains(srcRect)) {
159 }
160 }
161
162 SkPMColor4f color = texture_color(paint.getColor4f(), 1.f, srcColorInfo.colorType(), dstInfo);
163 if (dstClip) {
164 // Get source coords corresponding to dstClip
165 SkPoint srcQuad[4];
166 GrMapRectPoints(dstRect, srcRect, dstClip, srcQuad, 4);
167
169 std::move(view),
170 srcColorInfo.colorType(),
171 srcColorInfo.alphaType(),
172 filter,
173 GrSamplerState::MipmapMode::kNone,
174 paint.getBlendMode_or(SkBlendMode::kSrcOver),
175 color,
176 srcQuad,
177 dstClip,
178 aaFlags,
179 constraint == SkCanvas::kStrict_SrcRectConstraint ? &srcRect : nullptr,
180 ctm,
181 std::move(textureXform));
182 } else {
183 sdc->drawTexture(clip,
184 std::move(view),
185 srcColorInfo.alphaType(),
186 filter,
187 GrSamplerState::MipmapMode::kNone,
188 paint.getBlendMode_or(SkBlendMode::kSrcOver),
189 color,
190 srcRect,
191 dstRect,
192 aaFlags,
193 constraint,
194 ctm,
195 std::move(textureXform));
196 }
197}
198
199SkFilterMode downgrade_to_filter(const SkSamplingOptions& sampling) {
202 // if we were "fancier" than just bilerp, only do bilerp
203 filter = SkFilterMode::kLinear;
204 }
205 return filter;
206}
207
208} // anonymous namespace
209
210
211//////////////////////////////////////////////////////////////////////////////
212
213namespace skgpu::ganesh {
214
216 const SkRect& src,
217 const SkRect& dst,
218 const SkPoint dstClip[4],
219 SkCanvas::QuadAAFlags canvasAAFlags,
220 const SkMatrix& localToDevice,
221 const SkSamplingOptions& sampling,
222 const SkPaint& paint,
224 const SkMatrix& srcToDst,
225 SkTileMode tm) {
226 GrRecordingContext* rContext = fContext.get();
227 SurfaceDrawContext* sdc = fSurfaceDrawContext.get();
228 const GrClip* clip = this->clip();
229
230 GrQuadAAFlags aaFlags = SkToGrQuadAAFlags(canvasAAFlags);
231 auto ib = as_IB(image);
232 if (tm == SkTileMode::kClamp && !ib->isYUVA() && can_use_draw_texture(paint, sampling)) {
233 // We've done enough checks above to allow us to pass ClampNearest() and not check for
234 // scaling adjustments.
235 auto [view, ct] = skgpu::ganesh::AsView(rContext, image, skgpu::Mipmapped::kNo);
236 if (!view) {
237 return;
238 }
240 info = info.makeColorType(ct);
241 draw_texture(sdc,
242 clip,
244 paint,
245 sampling.filter,
246 src,
247 dst,
248 dstClip,
249 aaFlags,
250 constraint,
251 std::move(view),
252 info);
253 return;
254 }
255
256 const SkMaskFilter* mf = paint.getMaskFilter();
257
258 // The shader expects proper local coords, so we can't replace local coords with texture coords
259 // if the shader will be used. If we have a mask filter we will change the underlying geometry
260 // that is rendered.
261 bool canUseTextureCoordsAsLocalCoords = !use_shader(image->isAlphaOnly(), paint) && !mf;
262
263 // Specifying the texture coords as local coordinates is an attempt to enable more GrDrawOp
264 // combining by not baking anything about the srcRect, dstRect, or ctm, into the texture
265 // FP. In the future this should be an opaque optimization enabled by the combination of
266 // GrDrawOp/GP and FP.
268 mf = nullptr;
269 }
270
271 bool restrictToSubset = SkCanvas::kStrict_SrcRectConstraint == constraint;
272
273 // If we have to outset for AA then we will generate texture coords outside the src rect. The
274 // same happens for any mask filter that extends the bounds rendered in the dst.
275 // This is conservative as a mask filter does not have to expand the bounds rendered.
276 bool coordsAllInsideSrcRect = aaFlags == GrQuadAAFlags::kNone && !mf;
277
278 // Check for optimization to drop the src rect constraint when using linear filtering.
279 // TODO: Just rely on image to handle this.
280 if (sampling.isAniso() && !sampling.useCubic && sampling.filter == SkFilterMode::kLinear &&
281 restrictToSubset && sampling.mipmap == SkMipmapMode::kNone && coordsAllInsideSrcRect &&
282 !ib->isYUVA()) {
283 SkMatrix combinedMatrix;
284 combinedMatrix.setConcat(localToDevice, srcToDst);
285 if (can_ignore_linear_filtering_subset(src, combinedMatrix, sdc->numSamples())) {
286 restrictToSubset = false;
287 }
288 }
289
290 SkMatrix textureMatrix;
291 if (canUseTextureCoordsAsLocalCoords) {
292 textureMatrix = SkMatrix::I();
293 } else {
294 if (!srcToDst.invert(&textureMatrix)) {
295 return;
296 }
297 }
298 const SkRect* subset = restrictToSubset ? &src : nullptr;
299 const SkRect* domain = coordsAllInsideSrcRect ? &src : nullptr;
300 SkTileMode tileModes[] = {tm, tm};
301 std::unique_ptr<GrFragmentProcessor> fp = skgpu::ganesh::AsFragmentProcessor(
302 rContext, image, sampling, tileModes, textureMatrix, subset, domain);
304 std::move(fp), image->imageInfo().colorInfo(), sdc->colorInfo());
305 if (image->isAlphaOnly()) {
306 if (const auto* shader = as_SB(paint.getShader())) {
307 auto shaderFP = GrFragmentProcessors::Make(shader,
308 GrFPArgs(rContext,
309 &sdc->colorInfo(),
310 sdc->surfaceProps(),
313 if (!shaderFP) {
314 return;
315 }
316 fp = GrBlendFragmentProcessor::Make<SkBlendMode::kDstIn>(std::move(fp),
317 std::move(shaderFP));
318 } else {
319 // Multiply the input (paint) color by the texture (alpha)
321 }
322 }
323
324 GrPaint grPaint;
325 if (!SkPaintToGrPaintReplaceShader(rContext,
326 sdc->colorInfo(),
327 paint,
329 std::move(fp),
330 sdc->surfaceProps(),
331 &grPaint)) {
332 return;
333 }
334
335 if (!mf) {
336 // Can draw the image directly (any mask filter on the paint was converted to an FP already)
337 if (dstClip) {
338 SkPoint srcClipPoints[4];
339 SkPoint* srcClip = nullptr;
340 if (canUseTextureCoordsAsLocalCoords) {
341 // Calculate texture coordinates that match the dst clip
342 GrMapRectPoints(dst, src, dstClip, srcClipPoints, 4);
343 srcClip = srcClipPoints;
344 }
345 sdc->fillQuadWithEdgeAA(clip, std::move(grPaint), aaFlags, localToDevice,
346 dstClip, srcClip);
347 } else {
348 // Provide explicit texture coords when possible, otherwise rely on texture matrix
349 sdc->fillRectWithEdgeAA(clip, std::move(grPaint), aaFlags, localToDevice, dst,
350 canUseTextureCoordsAsLocalCoords ? &src : nullptr);
351 }
352 } else {
353 // Must draw the mask filter as a GrStyledShape. For now, this loses the per-edge AA
354 // information since it always draws with AA, but that should not be noticeable since the
355 // mask filter is probably a blur.
356 GrStyledShape shape;
357 if (dstClip) {
358 // Represent it as an SkPath formed from the dstClip
359 SkPath path;
360 path.addPoly(dstClip, 4, true);
361 shape = GrStyledShape(path);
362 } else {
363 shape = GrStyledShape(dst);
364 }
365
367 rContext, sdc, clip, shape, std::move(grPaint), localToDevice, mf);
368 }
369}
370
372 const SkMatrix& localToDevice,
373 const SkSamplingOptions& origSampling,
374 const SkPaint& paint,
375 SkCanvas::SrcRectConstraint constraint) {
376 SkASSERT(!paint.getMaskFilter() && !paint.getImageFilter());
377 SkASSERT(special->isGaneshBacked());
378
379 SkRect src = SkRect::Make(special->subset());
380 SkRect dst = SkRect::MakeWH(special->width(), special->height());
381 SkMatrix srcToDst = SkMatrix::RectToRect(src, dst);
382
383 SkSamplingOptions sampling = SkSamplingOptions(downgrade_to_filter(origSampling));
384 GrAA aa = fSurfaceDrawContext->chooseAA(paint);
387
388 GrSurfaceProxyView view = SkSpecialImages::AsView(this->recordingContext(), special);
389 if (!view) {
390 // This shouldn't happen since we shouldn't be mixing SkSpecialImage subclasses but
391 // returning early should avoid problems in release builds.
392 SkASSERT(false);
393 return;
394 }
395
396 if (constraint == SkCanvas::kFast_SrcRectConstraint) {
397 // If 'fast' was requested, we assume the caller has done sufficient analysis to know the
398 // logical dimensions are safe (which is true for FilterResult, the only current caller that
399 // passes in 'fast'). Without exactify'ing the proxy, GrTextureEffect would re-introduce
400 // subset clamping.
401 view.proxy()->priv().exactify();
402 }
403
405 special->uniqueID(),
406 std::move(view),
407 special->colorInfo());
408 // In most cases this ought to hit draw_texture since there won't be a color filter,
409 // alpha-only texture+shader, or a high filter quality.
410 this->drawEdgeAAImage(&image,
411 src,
412 dst,
413 /* dstClip= */nullptr,
414 aaFlags,
416 sampling,
417 paint,
418 constraint,
419 srcToDst,
421}
422
423void Device::drawImageQuadDirect(const SkImage* image,
424 const SkRect& srcRect,
425 const SkRect& dstRect,
426 const SkPoint dstClip[4],
427 SkCanvas::QuadAAFlags aaFlags,
428 const SkMatrix* preViewMatrix,
429 const SkSamplingOptions& origSampling,
430 const SkPaint& paint,
431 SkCanvas::SrcRectConstraint constraint) {
432 SkRect src;
433 SkRect dst;
434 SkMatrix srcToDst;
436 image->height()),
437 srcRect, dstRect, dstClip,
438 &src, &dst, &srcToDst);
440 return;
441 }
442
443 if (src.contains(image->bounds())) {
445 }
446 // Depending on the nature of image, it can flow through more or less optimal pipelines
449
450 // Get final CTM matrix
451 SkMatrix ctm = this->localToDevice();
452 if (preViewMatrix) {
453 ctm.preConcat(*preViewMatrix);
454 }
455
456 SkSamplingOptions sampling = origSampling;
460 }
461
462 this->drawEdgeAAImage(image,
463 src,
464 dst,
465 dstClip,
466 aaFlags,
467 ctm,
468 sampling,
469 paint,
470 constraint,
471 srcToDst,
472 tileMode);
473}
474
476 const SkPoint dstClips[], const SkMatrix preViewMatrices[],
477 const SkSamplingOptions& sampling, const SkPaint& paint,
478 SkCanvas::SrcRectConstraint constraint) {
479 SkASSERT(count > 0);
480 if (!can_use_draw_texture(paint, sampling)) {
481 // Send every entry through drawImageQuad() to handle the more complicated paint
482 int dstClipIndex = 0;
483 for (int i = 0; i < count; ++i) {
484 // Only no clip or quad clip are supported
485 SkASSERT(!set[i].fHasClip || dstClips);
486 SkASSERT(set[i].fMatrixIndex < 0 || preViewMatrices);
487
489 if (set[i].fAlpha != 1.f) {
490 auto paintAlpha = paint.getAlphaf();
491 entryPaint.writable()->setAlphaf(paintAlpha * set[i].fAlpha);
492 }
493 this->drawImageQuadDirect(
494 set[i].fImage.get(), set[i].fSrcRect, set[i].fDstRect,
495 set[i].fHasClip ? dstClips + dstClipIndex : nullptr,
496 static_cast<SkCanvas::QuadAAFlags>(set[i].fAAFlags),
497 set[i].fMatrixIndex < 0 ? nullptr : preViewMatrices + set[i].fMatrixIndex,
498 sampling, *entryPaint, constraint);
499 dstClipIndex += 4 * set[i].fHasClip;
500 }
501 return;
502 }
503
505 ? GrSamplerState::Filter::kNearest
506 : GrSamplerState::Filter::kLinear;
507 SkBlendMode mode = paint.getBlendMode_or(SkBlendMode::kSrcOver);
508
510 // We accumulate compatible proxies until we find an an incompatible one or reach the end and
511 // issue the accumulated 'n' draws starting at 'base'. 'p' represents the number of proxy
512 // switches that occur within the 'n' entries.
513 int base = 0, n = 0, p = 0;
514 auto draw = [&](int nextBase) {
515 if (n > 0) {
516 auto textureXform = GrColorSpaceXform::Make(set[base].fImage->imageInfo().colorInfo(),
517 fSurfaceDrawContext->colorInfo());
518 fSurfaceDrawContext->drawTextureSet(this->clip(),
519 textures.get() + base,
520 n,
521 p,
522 filter,
523 GrSamplerState::MipmapMode::kNone,
524 mode,
525 constraint,
526 this->localToDevice(),
527 std::move(textureXform));
528 }
529 base = nextBase;
530 n = 0;
531 p = 0;
532 };
533 int dstClipIndex = 0;
534 for (int i = 0; i < count; ++i) {
535 SkASSERT(!set[i].fHasClip || dstClips);
536 SkASSERT(set[i].fMatrixIndex < 0 || preViewMatrices);
537
538 // Manage the dst clip pointer tracking before any continues are used so we don't lose
539 // our place in the dstClips array.
540 const SkPoint* clip = set[i].fHasClip ? dstClips + dstClipIndex : nullptr;
541 dstClipIndex += 4 * set[i].fHasClip;
542
543 // The default SkDevice implementation is based on drawImageRect which does not allow
544 // non-sorted src rects. TODO: Decide this is OK or make sure we handle it.
545 if (!set[i].fSrcRect.isSorted()) {
546 draw(i + 1);
547 continue;
548 }
549
551 const SkImage_Base* image = as_IB(set[i].fImage.get());
552 // Extract view from image, but skip YUV images so they get processed through
553 // drawImageQuad and the proper effect to dynamically sample their planes.
554 if (!image->isYUVA()) {
555 std::tie(view, std::ignore) =
556 skgpu::ganesh::AsView(this->recordingContext(), image, skgpu::Mipmapped::kNo);
557 if (image->isAlphaOnly()) {
559 skgpu::Swizzle("aaaa"));
560 view = {view.detachProxy(), view.origin(), swizzle};
561 }
562 }
563
564 if (!view) {
565 // This image can't go through the texture op, send through general image pipeline
566 // after flushing current batch.
567 draw(i + 1);
569 if (set[i].fAlpha != 1.f) {
570 auto paintAlpha = paint.getAlphaf();
571 entryPaint.writable()->setAlphaf(paintAlpha * set[i].fAlpha);
572 }
573 this->drawImageQuadDirect(
574 image, set[i].fSrcRect, set[i].fDstRect, clip,
575 static_cast<SkCanvas::QuadAAFlags>(set[i].fAAFlags),
576 set[i].fMatrixIndex < 0 ? nullptr : preViewMatrices + set[i].fMatrixIndex,
577 sampling, *entryPaint, constraint);
578 continue;
579 }
580
581 textures[i].fProxyView = std::move(view);
582 textures[i].fSrcAlphaType = image->alphaType();
583 textures[i].fSrcRect = set[i].fSrcRect;
584 textures[i].fDstRect = set[i].fDstRect;
585 textures[i].fDstClipQuad = clip;
586 textures[i].fPreViewMatrix =
587 set[i].fMatrixIndex < 0 ? nullptr : preViewMatrices + set[i].fMatrixIndex;
588 textures[i].fColor = texture_color(paint.getColor4f(), set[i].fAlpha,
590 fSurfaceDrawContext->colorInfo());
591 textures[i].fAAFlags = SkToGrQuadAAFlags(set[i].fAAFlags);
592
593 if (n > 0 &&
595 textures[i].fProxyView.proxy(),
596 textures[base].fProxyView.proxy()) ||
597 textures[i].fProxyView.swizzle() != textures[base].fProxyView.swizzle() ||
598 set[i].fImage->alphaType() != set[base].fImage->alphaType() ||
599 !SkColorSpace::Equals(set[i].fImage->colorSpace(), set[base].fImage->colorSpace()))) {
600 draw(i);
601 }
602 // Whether or not we submitted a draw in the above if(), this ith entry is in the current
603 // set being accumulated so increment n, and increment p if proxies are different.
604 ++n;
605 if (n == 1 || textures[i - 1].fProxyView.proxy() != textures[i].fProxyView.proxy()) {
606 // First proxy or a different proxy (that is compatible, otherwise we'd have drawn up
607 // to i - 1).
608 ++p;
609 }
610 }
611 draw(count);
612}
613
614} // namespace skgpu::ganesh
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition DM.cpp:213
int count
static void GrMapRectPoints(const SkRect &inRect, const SkRect &outRect, const SkPoint inPts[], SkPoint outPts[], int ptCount)
Definition GrRect.h:37
GrQuadAAFlags
static GrQuadAAFlags SkToGrQuadAAFlags(unsigned flags)
static constexpr bool GrColorTypeIsAlphaOnly(GrColorType ct)
GrAA
GrColorType
static constexpr GrColorType SkColorTypeToGrColorType(SkColorType ct)
SkColor4f color
#define SkASSERT(cond)
Definition SkAssert.h:116
SkBlendMode
Definition SkBlendMode.h:38
@ kSrcOver
r = s + (1-sa)*d
bool SkPaintToGrPaintReplaceShader(GrRecordingContext *context, const GrColorInfo &dstColorInfo, const SkPaint &skPaint, const SkMatrix &ctm, std::unique_ptr< GrFragmentProcessor > shaderFP, const SkSurfaceProps &surfaceProps, GrPaint *grPaint)
Definition SkGr.cpp:570
SkColor4f SkColor4fPrepForDst(SkColor4f color, const GrColorInfo &colorInfo)
Definition SkGr.cpp:283
static SkImage_Base * as_IB(SkImage *image)
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
Definition SkPath.cpp:3824
sk_sp< T > sk_ref_sp(T *obj)
Definition SkRefCnt.h:381
SkFilterMode
#define SK_Scalar1
Definition SkScalar.h:18
#define SK_ScalarHalf
Definition SkScalar.h:19
#define SkScalarRoundToScalar(x)
Definition SkScalar.h:32
#define SkScalarAbs(x)
Definition SkScalar.h:39
SkShaderBase * as_SB(SkShader *shader)
static constexpr const T & SkTPin(const T &x, const T &lo, const T &hi)
Definition SkTPin.h:19
SkTileMode
Definition SkTileMode.h:13
static void draw(SkCanvas *canvas, SkRect &target, int x, int y)
Definition aaclip.cpp:27
GrColorType colorType() const
Definition GrColorInfo.h:43
SkAlphaType alphaType() const
Definition GrColorInfo.h:44
static std::unique_ptr< GrFragmentProcessor > Make(std::unique_ptr< GrFragmentProcessor > child, SkColorSpace *src, SkAlphaType srcAT, SkColorSpace *dst, SkAlphaType dstAT)
static sk_sp< GrColorSpaceXform > Make(SkColorSpace *src, SkAlphaType srcAT, SkColorSpace *dst, SkAlphaType dstAT)
static std::unique_ptr< GrFragmentProcessor > MulInputByChildAlpha(std::unique_ptr< GrFragmentProcessor > child)
skgpu::Swizzle swizzle() const
void concatSwizzle(skgpu::Swizzle swizzle)
sk_sp< GrSurfaceProxy > detachProxy()
GrSurfaceOrigin origin() const
GrSurfaceProxy * proxy() const
GrSurfaceProxyPriv priv()
SkRect getBoundsRect() const
bool isFunctionallyExact() const
static constexpr float kLinearInset
static bool ProxiesAreCompatibleAsDynamicState(const GrSurfaceProxy *first, const GrSurfaceProxy *second)
SrcRectConstraint
Definition SkCanvas.h:1541
@ kStrict_SrcRectConstraint
sample only inside bounds; slower
Definition SkCanvas.h:1542
@ kFast_SrcRectConstraint
sample outside bounds; faster
Definition SkCanvas.h:1543
@ kNone_QuadAAFlags
Definition SkCanvas.h:1664
@ kAll_QuadAAFlags
Definition SkCanvas.h:1665
static bool Equals(const SkColorSpace *, const SkColorSpace *)
const SkMatrix & localToDevice() const
Definition SkDevice.h:179
bool isAlphaOnly() const
Definition SkImage.cpp:239
const SkImageInfo & imageInfo() const
Definition SkImage.h:279
SkAlphaType alphaType() const
Definition SkImage.cpp:154
int width() const
Definition SkImage.h:285
SkColorType colorType() const
Definition SkImage.cpp:152
int height() const
Definition SkImage.h:291
SkIRect bounds() const
Definition SkImage.h:303
static SkMatrix RectToRect(const SkRect &src, const SkRect &dst, ScaleToFit mode=kFill_ScaleToFit)
Definition SkMatrix.h:157
bool invert(SkMatrix *inverse) const
Definition SkMatrix.h:1206
bool rectStaysRect() const
Definition SkMatrix.h:271
static const SkMatrix & I()
SkMatrix & preConcat(const SkMatrix &other)
Definition SkMatrix.cpp:674
bool mapRect(SkRect *dst, const SkRect &src, SkApplyPerspectiveClip pc=SkApplyPerspectiveClip::kYes) const
SkMatrix & setConcat(const SkMatrix &a, const SkMatrix &b)
Definition SkMatrix.cpp:603
int width() const
int height() const
virtual GrRecordingContext * getContext() const
virtual bool isGaneshBacked() const
uint32_t uniqueID() const
const SkIRect & subset() const
const SkColorInfo & colorInfo() const
T * get() const
Definition SkRefCnt.h:303
static constexpr Swizzle Concat(const Swizzle &a, const Swizzle &b)
Definition Swizzle.h:156
static ImageDrawMode OptimizeSampleArea(const SkISize &imageSize, const SkRect &origSrcRect, const SkRect &origDstRect, const SkPoint dstClip[4], SkRect *outSrcRect, SkRect *outDstRect, SkMatrix *outSrcToDst)
static bool CanDisableMipmap(const SkMatrix &viewM, const SkMatrix &localM)
void drawEdgeAAImageSet(const SkCanvas::ImageSetEntry[], int count, const SkPoint dstClips[], const SkMatrix preViewMatrices[], const SkSamplingOptions &, const SkPaint &, SkCanvas::SrcRectConstraint) override
void drawSpecial(SkSpecialImage *, const SkMatrix &localToDevice, const SkSamplingOptions &, const SkPaint &, SkCanvas::SrcRectConstraint) override
void drawEdgeAAImage(const SkImage *, const SkRect &src, const SkRect &dst, const SkPoint dstClip[4], SkCanvas::QuadAAFlags, const SkMatrix &localToDevice, const SkSamplingOptions &, const SkPaint &, SkCanvas::SrcRectConstraint, const SkMatrix &srcToDst, SkTileMode)
GrRecordingContext * recordingContext() const override
Definition Device.h:101
const GrColorInfo & colorInfo() const
void fillQuadWithEdgeAA(const GrClip *clip, GrPaint &&paint, GrQuadAAFlags edgeAA, const SkMatrix &viewMatrix, const SkPoint points[4], const SkPoint optionalLocalPoints[4])
void fillRectWithEdgeAA(const GrClip *clip, GrPaint &&paint, GrQuadAAFlags edgeAA, const SkMatrix &viewMatrix, const SkRect &rect, const SkRect *optionalLocalRect=nullptr)
void drawTextureQuad(const GrClip *clip, GrSurfaceProxyView view, GrColorType srcColorType, SkAlphaType srcAlphaType, GrSamplerState::Filter filter, GrSamplerState::MipmapMode mm, SkBlendMode mode, const SkPMColor4f &color, const SkPoint srcQuad[4], const SkPoint dstQuad[4], GrQuadAAFlags edgeAA, const SkRect *subset, const SkMatrix &viewMatrix, sk_sp< GrColorSpaceXform > texXform)
const SkSurfaceProps & surfaceProps() const
void drawTexture(const GrClip *, GrSurfaceProxyView, SkAlphaType, GrSamplerState::Filter, GrSamplerState::MipmapMode, SkBlendMode, const SkPMColor4f &, const SkRect &srcRect, const SkRect &dstRect, GrQuadAAFlags, SkCanvas::SrcRectConstraint, const SkMatrix &, sk_sp< GrColorSpaceXform >)
const Paint & paint
std::vector< std::shared_ptr< FakeTexture > > textures
sk_sp< SkImage > image
Definition examples.cpp:29
float SkScalar
Definition extension.cpp:12
static const uint8_t buffer[]
static void draw_texture(const GrCaps *caps, skgpu::ganesh::SurfaceDrawContext *sdc, const GrSurfaceProxyView &src, const SkIRect &srcRect, const SkIRect &drawRect, const SkMatrix &mat, GrSamplerState::WrapMode xTileMode, GrSamplerState::WrapMode yTileMode)
void DrawShapeWithMaskFilter(GrRecordingContext *rContext, skgpu::ganesh::SurfaceDrawContext *sdc, const GrClip *clip, const GrStyledShape &shape, GrPaint &&paint, const SkMatrix &viewMatrix, const SkMaskFilter *mf)
std::unique_ptr< GrFragmentProcessor > Make(const SkMaskFilter *maskfilter, const GrFPArgs &args, const SkMatrix &ctm)
bool IsSupported(const SkMaskFilter *maskfilter)
SkSamplingOptions sampling
Definition SkRecords.h:337
std::unique_ptr< GrFragmentProcessor > AsFragmentProcessor(GrRecordingContext *rContext, const SkImage *img, SkSamplingOptions sampling, const SkTileMode tileModes[2], const SkMatrix &m, const SkRect *subset, const SkRect *domain)
std::tuple< GrSurfaceProxyView, GrColorType > AsView(GrRecordingContext *rContext, const SkImage *img, skgpu::Mipmapped mipmapped, GrImageTexGenPolicy policy)
Definition ref_ptr.h:256
static constexpr SkISize Make(int32_t w, int32_t h)
Definition SkSize.h:20
const SkColorInfo & colorInfo() const
static SkRect Make(const SkISize &size)
Definition SkRect.h:669
constexpr float left() const
Definition SkRect.h:734
void inset(float dx, float dy)
Definition SkRect.h:1060
constexpr float top() const
Definition SkRect.h:741
void outset(float dx, float dy)
Definition SkRect.h:1077
bool contains(SkScalar x, SkScalar y) const
Definition extension.cpp:19
void round(SkIRect *dst) const
Definition SkRect.h:1228
constexpr float height() const
Definition SkRect.h:769
constexpr float width() const
Definition SkRect.h:762
static constexpr SkRect MakeWH(float w, float h)
Definition SkRect.h:609
const SkFilterMode filter
const SkMipmapMode mipmap