Flutter Engine
The Flutter Engine
TextureUtils.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2022 Google LLC
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
18#include "src/core/SkDevice.h"
21#include "src/core/SkMipmap.h"
25
34#include "src/gpu/BlurUtils.h"
52
53#include <array>
54
55
59
60namespace skgpu::graphite {
61
62namespace {
63
64sk_sp<Surface> make_renderable_scratch_surface(
65 Recorder* recorder,
66 const SkImageInfo& info,
67 SkBackingFit backingFit,
68 std::string_view label,
69 const SkSurfaceProps* surfaceProps = nullptr) {
70 SkColorType ct = recorder->priv().caps()->getRenderableColorType(info.colorType());
71 if (ct == kUnknown_SkColorType) {
72 return nullptr;
73 }
74
75 // TODO(b/323886870): Historically the scratch surfaces used here were exact-fit but they should
76 // be able to be approx-fit and uninstantiated.
77 return Surface::MakeScratch(recorder,
78 info.makeColorType(ct),
79 std::move(label),
82 backingFit);
83}
84
85bool valid_client_provided_image(const SkImage* clientProvided,
86 const SkImage* original,
87 SkImage::RequiredProperties requiredProps) {
88 if (!clientProvided ||
89 !as_IB(clientProvided)->isGraphiteBacked() ||
90 original->dimensions() != clientProvided->dimensions() ||
91 original->alphaType() != clientProvided->alphaType()) {
92 return false;
93 }
94
95 uint32_t origChannels = SkColorTypeChannelFlags(original->colorType());
96 uint32_t clientChannels = SkColorTypeChannelFlags(clientProvided->colorType());
97 if ((origChannels & clientChannels) != origChannels) {
98 return false;
99 }
100
101 // We require provided images to have a TopLeft origin
102 auto graphiteImage = static_cast<const Image*>(clientProvided);
103 if (graphiteImage->textureProxyView().origin() != Origin::kTopLeft) {
104 SKGPU_LOG_E("Client provided image must have a TopLeft origin.");
105 return false;
106 }
107
108 return true;
109}
110
111#if defined(SK_USE_LEGACY_BLUR_GRAPHITE)
112
113sk_sp<SkSpecialImage> eval_blur(Recorder* recorder,
114 sk_sp<SkShader> blurEffect,
115 const SkIRect& dstRect,
118 const SkSurfaceProps& outProps) {
119 SkImageInfo outII = SkImageInfo::Make({dstRect.width(), dstRect.height()},
120 colorType, kPremul_SkAlphaType, std::move(outCS));
121 // Protected-ness is pulled off of the recorder
122 auto device = Device::Make(recorder,
123 outII,
127 outProps,
129 "EvalBlurTexture");
130 if (!device) {
131 return nullptr;
132 }
133
134 // TODO(b/294102201): This is very much like AutoSurface in SkImageFilterTypes.cpp
135 SkIRect subset = SkIRect::MakeSize(dstRect.size());
136 device->clipRect(SkRect::Make(subset), SkClipOp::kIntersect, /*aa=*/false);
137 device->setLocalToDevice(SkM44::Translate(-dstRect.left(), -dstRect.top()));
139 paint.setBlendMode(SkBlendMode::kSrc);
140 paint.setShader(std::move(blurEffect));
141 device->drawPaint(paint);
142 return device->snapSpecial(subset);
143}
144
145sk_sp<SkSpecialImage> blur_2d(Recorder* recorder,
146 SkSize sigma,
147 SkISize radii,
149 const SkIRect& srcRect,
150 SkTileMode tileMode,
151 const SkIRect& dstRect,
153 const SkSurfaceProps& outProps) {
154 std::array<SkV4, kMaxBlurSamples/4> kernel;
155 std::array<SkV4, kMaxBlurSamples/2> offsets;
156 Compute2DBlurKernel(sigma, radii, kernel);
158
160 builder.uniform("kernel") = kernel;
161 builder.uniform("offsets") = offsets;
162 // TODO(b/294102201): This is very much like FilterResult::asShader()...
163 builder.child("child") =
164 input->makeSubset(srcRect)->asShader(tileMode,
166 SkMatrix::Translate(srcRect.left(),srcRect.top()));
167
168 return eval_blur(recorder, builder.makeShader(), dstRect,
169 input->colorType(), std::move(outCS), outProps);
170}
171
172sk_sp<SkSpecialImage> blur_1d(Recorder* recorder,
173 float sigma,
174 int radius,
175 SkV2 dir,
177 SkIRect srcRect,
178 SkTileMode tileMode,
179 SkIRect dstRect,
181 const SkSurfaceProps& outProps) {
182 std::array<SkV4, kMaxBlurSamples/2> offsetsAndKernel;
183 Compute1DBlurLinearKernel(sigma, radius, offsetsAndKernel);
184
186 builder.uniform("offsetsAndKernel") = offsetsAndKernel;
187 builder.uniform("dir") = dir;
188 // TODO(b/294102201): This is very much like FilterResult::asShader()...
189 builder.child("child") =
190 input->makeSubset(srcRect)->asShader(tileMode,
192 SkMatrix::Translate(srcRect.left(),srcRect.top()));
193
194 return eval_blur(recorder, builder.makeShader(), dstRect,
195 input->colorType(), std::move(outCS), outProps);
196}
197
198sk_sp<SkSpecialImage> blur_impl(Recorder* recorder,
199 SkSize sigma,
201 SkIRect srcRect,
202 SkTileMode tileMode,
203 SkIRect dstRect,
205 const SkSurfaceProps& outProps) {
206 // See if we can do a blur on the original resolution image
207 if (sigma.width() <= kMaxLinearBlurSigma &&
208 sigma.height() <= kMaxLinearBlurSigma) {
209 int radiusX = BlurSigmaRadius(sigma.width());
210 int radiusY = BlurSigmaRadius(sigma.height());
211 const int kernelArea = BlurKernelWidth(radiusX) * BlurKernelWidth(radiusY);
212 if (kernelArea <= kMaxBlurSamples && radiusX > 0 && radiusY > 0) {
213 // Use a single-pass 2D kernel if it fits and isn't just 1D already
214 return blur_2d(recorder, sigma, {radiusX, radiusY}, std::move(input), srcRect, tileMode,
215 dstRect, std::move(outCS), outProps);
216 } else {
217 // Use two passes of a 1D kernel (one per axis).
218 if (radiusX > 0) {
219 SkIRect intermediateDstRect = dstRect;
220 if (radiusY > 0) {
221 // Outset the output size of dstRect by the radius required for the next Y pass
222 intermediateDstRect.outset(0, radiusY);
223 if (!intermediateDstRect.intersect(srcRect.makeOutset(radiusX, radiusY))) {
224 return nullptr;
225 }
226 }
227
228 input = blur_1d(recorder, sigma.width(), radiusX, {1.f, 0.f},
229 std::move(input), srcRect, tileMode, intermediateDstRect,
230 outCS, outProps);
231 if (!input) {
232 return nullptr;
233 }
234 srcRect = SkIRect::MakeWH(input->width(), input->height());
235 dstRect.offset(-intermediateDstRect.left(), -intermediateDstRect.top());
236 }
237
238 if (radiusY > 0) {
239 input = blur_1d(recorder, sigma.height(), radiusY, {0.f, 1.f},
240 std::move(input), srcRect, tileMode, dstRect, outCS, outProps);
241 }
242
243 return input;
244 }
245 } else {
246 // Rescale the source image, blur that with a reduced sigma, and then upscale back to the
247 // dstRect dimensions.
248 // TODO(b/294102201): Share rescaling logic with GrBlurUtils::GaussianBlur.
249 float sx = sigma.width() > kMaxLinearBlurSigma
250 ? (kMaxLinearBlurSigma / sigma.width()) : 1.f;
251 float sy = sigma.height() > kMaxLinearBlurSigma
252 ? (kMaxLinearBlurSigma / sigma.height()) : 1.f;
253
254 int targetSrcWidth = sk_float_ceil2int(srcRect.width() * sx);
255 int targetSrcHeight = sk_float_ceil2int(srcRect.height() * sy);
256
257 auto inputImage = input->asImage();
258 // TODO(b/288902559): Support approx fit backings for the target of a rescale
259 // TODO(b/294102201): Be smarter about downscaling when there are actual tilemodes to apply
260 // to the image.
261 auto scaledInput = RescaleImage(
262 recorder,
263 inputImage.get(),
264 srcRect.makeOffset(input->subset().topLeft()),
265 inputImage->imageInfo().makeWH(targetSrcWidth, targetSrcHeight),
268 if (!scaledInput) {
269 return nullptr;
270 }
271
272 // Calculate a scaled dstRect to match (0,0,targetSrcWidth,targetSrcHeight) as srcRect.
273 SkIRect targetDstRect = SkRect::MakeXYWH((dstRect.left() - srcRect.left()) * sx,
274 (dstRect.top() - srcRect.top()) * sy,
275 dstRect.width()*sx,
276 dstRect.height()*sy).roundOut();
277 SkIRect targetSrcRect = SkIRect::MakeWH(targetSrcWidth, targetSrcHeight);
278 // Blur with pinned sigmas. If the sigma was less than the max, that axis of the image was
279 // not scaled so we can use the original. If it was greater than the max, the scale factor
280 // should have taken it the max supported sigma (ignoring the effect of rounding out the
281 // source bounds).
282 auto scaledOutput = blur_impl(
283 recorder,
287 targetSrcRect,
288 std::move(scaledInput),
289 outProps),
290 targetSrcRect,
291 tileMode,
292 targetDstRect,
293 outCS,
294 outProps);
295 if (!scaledOutput) {
296 return nullptr;
297 }
298
299 // TODO: Pass out the upscaling transform for skif::FilterResult to hold on to.
300 auto scaledOutputImage = scaledOutput->asImage();
301 auto outputImage = RescaleImage(
302 recorder,
303 scaledOutputImage.get(),
304 scaledOutput->subset(),
305 scaledOutputImage->imageInfo().makeWH(dstRect.width(), dstRect.height()),
308 if (!outputImage) {
309 return nullptr;
310 }
311
312 SkIRect outputDstRect = outputImage->bounds();
313 return SkSpecialImages::MakeGraphite(recorder,
314 outputDstRect,
315 std::move(outputImage),
316 outProps);
317 }
318}
319
320#endif // SK_USE_LEGACY_BLUR_GRAPHITE
321
322// This class is the lazy instantiation callback for promise images. It manages calling the
323// client's Fulfill, ImageRelease, and TextureRelease procs.
324class PromiseLazyInstantiateCallback {
325public:
326 PromiseLazyInstantiateCallback(sk_sp<RefCntedCallback> releaseHelper,
329 GraphitePromiseTextureReleaseProc textureReleaseProc,
330 std::string_view label)
331 : fReleaseHelper(std::move(releaseHelper))
332 , fFulfillProc(fulfillProc)
333 , fFulfillContext(fulfillContext)
334 , fTextureReleaseProc(textureReleaseProc)
335 , fLabel(label) {
336 }
337 PromiseLazyInstantiateCallback(PromiseLazyInstantiateCallback&&) = default;
338 PromiseLazyInstantiateCallback(const PromiseLazyInstantiateCallback&) {
339 // Because we get wrapped in std::function we must be copyable. But we should never
340 // be copied.
341 SkASSERT(false);
342 }
343 PromiseLazyInstantiateCallback& operator=(PromiseLazyInstantiateCallback&&) = default;
344 PromiseLazyInstantiateCallback& operator=(const PromiseLazyInstantiateCallback&) {
345 SkASSERT(false);
346 return *this;
347 }
348
349 sk_sp<Texture> operator()(ResourceProvider* resourceProvider) {
350 // Invoke the fulfill proc to get the promised backend texture.
351 auto [ backendTexture, textureReleaseCtx ] = fFulfillProc(fFulfillContext);
352 if (!backendTexture.isValid()) {
353 SKGPU_LOG_W("FulfillProc returned an invalid backend texture");
354 return nullptr;
355 }
356
357 sk_sp<RefCntedCallback> textureReleaseCB = RefCntedCallback::Make(fTextureReleaseProc,
358 textureReleaseCtx);
359
360 sk_sp<Texture> texture = resourceProvider->createWrappedTexture(backendTexture,
361 std::move(fLabel));
362 if (!texture) {
363 SKGPU_LOG_W("Failed to wrap BackendTexture returned by fulfill proc");
364 return nullptr;
365 }
366 texture->setReleaseCallback(std::move(textureReleaseCB));
367 return texture;
368 }
369
370private:
371 sk_sp<RefCntedCallback> fReleaseHelper;
374 GraphitePromiseTextureReleaseProc fTextureReleaseProc;
375 std::string fLabel;
376};
377
378} // anonymous namespace
379
380std::tuple<TextureProxyView, SkColorType> MakeBitmapProxyView(Recorder* recorder,
381 const SkBitmap& bitmap,
382 sk_sp<SkMipmap> mipmapsIn,
383 Mipmapped mipmapped,
384 Budgeted budgeted,
385 std::string_view label) {
386 // Adjust params based on input and Caps
387 const Caps* caps = recorder->priv().caps();
388 SkColorType ct = bitmap.info().colorType();
389
390 if (bitmap.dimensions().area() <= 1) {
391 mipmapped = Mipmapped::kNo;
392 }
393
394 Protected isProtected = recorder->priv().isProtected();
395 auto textureInfo = caps->getDefaultSampledTextureInfo(ct, mipmapped, isProtected,
397 if (!textureInfo.isValid()) {
399 textureInfo = caps->getDefaultSampledTextureInfo(ct, mipmapped, isProtected,
401 }
402 SkASSERT(textureInfo.isValid());
403
404 // Convert bitmap to texture colortype if necessary
405 SkBitmap bmpToUpload;
406 if (ct != bitmap.info().colorType()) {
407 if (!bmpToUpload.tryAllocPixels(bitmap.info().makeColorType(ct)) ||
408 !bitmap.readPixels(bmpToUpload.pixmap())) {
409 return {};
410 }
411 bmpToUpload.setImmutable();
412 } else {
413 bmpToUpload = bitmap;
414 }
415
416 if (!SkImageInfoIsValid(bmpToUpload.info())) {
417 return {};
418 }
419
420 int mipLevelCount = (mipmapped == Mipmapped::kYes) ?
421 SkMipmap::ComputeLevelCount(bitmap.width(), bitmap.height()) + 1 : 1;
422
423
424 // setup MipLevels
425 sk_sp<SkMipmap> mipmaps;
426 std::vector<MipLevel> texels;
427 if (mipLevelCount == 1) {
428 texels.resize(mipLevelCount);
429 texels[0].fPixels = bmpToUpload.getPixels();
430 texels[0].fRowBytes = bmpToUpload.rowBytes();
431 } else {
432 mipmaps = SkToBool(mipmapsIn)
433 ? mipmapsIn
434 : sk_sp<SkMipmap>(SkMipmap::Build(bmpToUpload.pixmap(), nullptr));
435 if (!mipmaps) {
436 return {};
437 }
438
439 SkASSERT(mipLevelCount == mipmaps->countLevels() + 1);
440 texels.resize(mipLevelCount);
441
442 texels[0].fPixels = bmpToUpload.getPixels();
443 texels[0].fRowBytes = bmpToUpload.rowBytes();
444
445 for (int i = 1; i < mipLevelCount; ++i) {
446 SkMipmap::Level generatedMipLevel;
447 mipmaps->getLevel(i - 1, &generatedMipLevel);
448 texels[i].fPixels = generatedMipLevel.fPixmap.addr();
449 texels[i].fRowBytes = generatedMipLevel.fPixmap.rowBytes();
450 SkASSERT(texels[i].fPixels);
451 SkASSERT(generatedMipLevel.fPixmap.colorType() == bmpToUpload.colorType());
452 }
453 }
454
455 // Create proxy
457 recorder->priv().resourceProvider(),
458 bmpToUpload.dimensions(),
459 textureInfo,
460 std::move(label),
461 budgeted);
462 if (!proxy) {
463 return {};
464 }
465 SkASSERT(caps->areColorTypeAndTextureInfoCompatible(ct, proxy->textureInfo()));
466 SkASSERT(mipmapped == Mipmapped::kNo || proxy->mipmapped() == Mipmapped::kYes);
467
468 // Src and dst colorInfo are the same
469 const SkColorInfo& colorInfo = bmpToUpload.info().colorInfo();
470 // Add UploadTask to Recorder
472 recorder, proxy, colorInfo, colorInfo, texels,
473 SkIRect::MakeSize(bmpToUpload.dimensions()), std::make_unique<ImageUploadContext>());
474 if (!upload.isValid()) {
475 SKGPU_LOG_E("MakeBitmapProxyView: Could not create UploadInstance");
476 return {};
477 }
478 recorder->priv().add(UploadTask::Make(std::move(upload)));
479
480 Swizzle swizzle = caps->getReadSwizzle(ct, textureInfo);
481 // If the color type is alpha-only, propagate the alpha value to the other channels.
482 if (SkColorTypeIsAlphaOnly(colorInfo.colorType())) {
483 swizzle = Swizzle::Concat(swizzle, Swizzle("aaaa"));
484 }
485 return {{std::move(proxy), swizzle}, ct};
486}
487
489 const Caps* caps,
490 SkISize dimensions,
491 TextureInfo textureInfo,
492 Volatile isVolatile,
493 sk_sp<RefCntedCallback> releaseHelper,
496 GraphitePromiseTextureReleaseProc textureReleaseProc,
497 std::string_view label) {
498 SkASSERT(!dimensions.isEmpty());
499 SkASSERT(releaseHelper);
500
501 if (!fulfillProc) {
502 return nullptr;
503 }
504
505 PromiseLazyInstantiateCallback callback{std::move(releaseHelper), fulfillProc,
506 fulfillContext, textureReleaseProc, std::move(label)};
507 // Proxies for promise images are assumed to always be destined for a client's SkImage so
508 // are never considered budgeted.
509 return TextureProxy::MakeLazy(caps, dimensions, textureInfo, Budgeted::kNo, isVolatile,
510 std::move(callback));
511}
512
514 const SkColorInfo& colorInfo,
515 const SkBitmap& bitmap,
516 sk_sp<SkMipmap> mipmaps,
517 Budgeted budgeted,
518 SkImage::RequiredProperties requiredProps,
519 std::string_view label) {
520 auto mm = requiredProps.fMipmapped ? Mipmapped::kYes : Mipmapped::kNo;
521 auto [view, ct] = MakeBitmapProxyView(recorder,
522 bitmap,
523 std::move(mipmaps),
524 mm,
525 budgeted,
526 std::move(label));
527 if (!view) {
528 return nullptr;
529 }
530
531 SkASSERT(!requiredProps.fMipmapped || view.proxy()->mipmapped() == Mipmapped::kYes);
532 return sk_make_sp<skgpu::graphite::Image>(std::move(view), colorInfo.makeColorType(ct));
533}
534
535size_t ComputeSize(SkISize dimensions,
536 const TextureInfo& info) {
537
538 SkTextureCompressionType compression = info.compressionType();
539
540 size_t colorSize = 0;
541
542 if (compression != SkTextureCompressionType::kNone) {
543 colorSize = SkCompressedFormatDataSize(compression,
544 dimensions,
545 info.mipmapped() == Mipmapped::kYes);
546 } else {
547 // TODO: Should we make sure the backends return zero here if the TextureInfo is for a
548 // memoryless texture?
549 size_t bytesPerPixel = info.bytesPerPixel();
550
551 colorSize = (size_t)dimensions.width() * dimensions.height() * bytesPerPixel;
552 }
553
554 size_t finalSize = colorSize * info.numSamples();
555
556 if (info.mipmapped() == Mipmapped::kYes) {
557 finalSize += colorSize/3;
558 }
559 return finalSize;
560}
561
563 const SkImage* image,
564 const SkIRect& subset,
565 const SkColorInfo& dstColorInfo,
566 Budgeted budgeted,
567 Mipmapped mipmapped,
568 SkBackingFit backingFit,
569 std::string_view label) {
570 SkColorType ct = recorder->priv().caps()->getRenderableColorType(dstColorInfo.colorType());
571 if (ct == kUnknown_SkColorType) {
572 return nullptr;
573 }
574 SkImageInfo dstInfo = SkImageInfo::Make(subset.size(),
575 dstColorInfo.makeColorType(ct)
577 // The surface goes out of scope when we return, so it can be scratch, but it may or may
578 // not be budgeted depending on how the copied image is used (or returned to the client).
579 auto surface = Surface::MakeScratch(recorder,
580 dstInfo,
581 std::move(label),
582 budgeted,
583 mipmapped,
584 backingFit);
585 if (!surface) {
586 return nullptr;
587 }
588
590 paint.setBlendMode(SkBlendMode::kSrc);
591 surface->getCanvas()->drawImage(image, -subset.left(), -subset.top(),
593 // And the image draw into `surface` is flushed when it goes out of scope
594 return surface->asImage();
595}
596
598 const SkImage* srcImage,
599 SkIRect srcIRect,
600 const SkImageInfo& dstInfo,
601 SkImage::RescaleGamma rescaleGamma,
602 SkImage::RescaleMode rescaleMode) {
603 TRACE_EVENT0("skia.gpu", TRACE_FUNC);
604 TRACE_EVENT_INSTANT2("skia.gpu", "RescaleImage Src", TRACE_EVENT_SCOPE_THREAD,
605 "width", srcIRect.width(), "height", srcIRect.height());
606 TRACE_EVENT_INSTANT2("skia.gpu", "RescaleImage Dst", TRACE_EVENT_SCOPE_THREAD,
607 "width", dstInfo.width(), "height", dstInfo.height());
608
609 // RescaleImage() should only be called when we already know that srcImage is graphite-backed
610 SkASSERT(srcImage && as_IB(srcImage)->isGraphiteBacked());
611
612 // For now this needs to be texturable because we can't depend on copies to scale.
613 // NOTE: srcView may be empty if srcImage is YUVA.
614 const TextureProxyView srcView = AsView(srcImage);
615 if (srcView && !recorder->priv().caps()->isTexturable(srcView.proxy()->textureInfo())) {
616 // With the current definition of SkImage, this shouldn't happen. If we allow non-texturable
617 // formats for compute, we'll need to copy to a texturable format.
618 SkASSERT(false);
619 return nullptr;
620 }
621
622 // make a Surface *exactly* matching dstInfo to rescale into
623 SkSurfaceProps surfaceProps = {};
624 sk_sp<SkSurface> dst = make_renderable_scratch_surface(recorder,
625 dstInfo,
627 "RescaleDstTexture",
628 &surfaceProps);
629 if (!dst) {
630 return nullptr;
631 }
632
633 SkRect srcRect = SkRect::Make(srcIRect);
634 SkRect dstRect = SkRect::Make(dstInfo.dimensions());
635
636 SkISize finalSize = SkISize::Make(dstRect.width(), dstRect.height());
637 if (finalSize == srcIRect.size()) {
638 rescaleGamma = Image::RescaleGamma::kSrc;
639 rescaleMode = Image::RescaleMode::kNearest;
640 }
641
642 // Within a rescaling pass tempInput is read from and tempOutput is written to.
643 // At the end of the pass tempOutput's texture is wrapped and assigned to tempInput.
644 sk_sp<SkImage> tempInput = sk_ref_sp(srcImage);
645 sk_sp<SkSurface> tempOutput;
646
647 // Assume we should ignore the rescale linear request if the surface has no color space since
648 // it's unclear how we'd linearize from an unknown color space.
649 const SkImageInfo& srcImageInfo = srcImage->imageInfo();
650 if (rescaleGamma == Image::RescaleGamma::kLinear &&
651 srcImageInfo.colorSpace() &&
652 !srcImageInfo.colorSpace()->gammaIsLinear()) {
653 // Draw the src image into a new surface with linear gamma, and make that the new tempInput
654 sk_sp<SkColorSpace> linearGamma = srcImageInfo.colorSpace()->makeLinearGamma();
655 SkImageInfo gammaDstInfo = SkImageInfo::Make(srcIRect.size(),
656 tempInput->imageInfo().colorType(),
658 std::move(linearGamma));
659 tempOutput = make_renderable_scratch_surface(recorder, gammaDstInfo, SkBackingFit::kApprox,
660 "RescaleLinearGammaTexture", &surfaceProps);
661 if (!tempOutput) {
662 return nullptr;
663 }
664 SkCanvas* gammaDst = tempOutput->getCanvas();
665 SkRect gammaDstRect = SkRect::Make(srcIRect.size());
666
668 paint.setBlendMode(SkBlendMode::kSrc);
669 gammaDst->drawImageRect(tempInput, srcRect, gammaDstRect,
672 tempInput = SkSurfaces::AsImage(std::move(tempOutput));
673 srcRect = gammaDstRect;
674 }
675
676 SkImageInfo outImageInfo = tempInput->imageInfo().makeAlphaType(kPremul_SkAlphaType);
677 do {
678 SkISize nextDims = finalSize;
679 if (rescaleMode != Image::RescaleMode::kNearest &&
680 rescaleMode != Image::RescaleMode::kLinear) {
681 if (srcRect.width() > finalSize.width()) {
682 nextDims.fWidth = std::max((srcRect.width() + 1)/2, (float)finalSize.width());
683 } else if (srcRect.width() < finalSize.width()) {
684 nextDims.fWidth = std::min(srcRect.width()*2, (float)finalSize.width());
685 }
686 if (srcRect.height() > finalSize.height()) {
687 nextDims.fHeight = std::max((srcRect.height() + 1)/2, (float)finalSize.height());
688 } else if (srcRect.height() < finalSize.height()) {
689 nextDims.fHeight = std::min(srcRect.height()*2, (float)finalSize.height());
690 }
691 }
692
693 SkRect stepDstRect;
694 if (nextDims == finalSize) {
695 tempOutput = dst;
696 stepDstRect = dstRect;
697 } else {
698 SkImageInfo nextInfo = outImageInfo.makeDimensions(nextDims);
699 tempOutput = make_renderable_scratch_surface(recorder, nextInfo, SkBackingFit::kApprox,
700 "RescaleImageTempTexture", &surfaceProps);
701 if (!tempOutput) {
702 return nullptr;
703 }
704 stepDstRect = SkRect::Make(tempOutput->imageInfo().dimensions());
705 }
706
707 SkSamplingOptions samplingOptions;
708 if (rescaleMode == Image::RescaleMode::kRepeatedCubic) {
710 } else {
711 samplingOptions = (rescaleMode == Image::RescaleMode::kNearest) ?
714 }
716 paint.setBlendMode(SkBlendMode::kSrc);
717 tempOutput->getCanvas()->drawImageRect(tempInput, srcRect, stepDstRect, samplingOptions,
719
720 tempInput = SkSurfaces::AsImage(std::move(tempOutput));
721 srcRect = SkRect::Make(nextDims);
722 } while (srcRect.width() != finalSize.width() || srcRect.height() != finalSize.height());
723
724 return SkSurfaces::AsImage(std::move(dst));
725}
726
729 const SkColorInfo& colorInfo) {
730 constexpr SkSamplingOptions kSamplingOptions = SkSamplingOptions(SkFilterMode::kLinear);
731
732 SkASSERT(texture->mipmapped() == Mipmapped::kYes);
733
734 // Within a rescaling pass scratchImg is read from and a scratch surface is written to.
735 // At the end of the pass the scratch surface's texture is wrapped and assigned to scratchImg.
736
737 // The scratch surface we create below will use a write swizzle derived from SkColorType and
738 // pixel format. We have to be consistent and swizzle on the read.
739 auto imgSwizzle = recorder->priv().caps()->getReadSwizzle(colorInfo.colorType(),
740 texture->textureInfo());
741 sk_sp<SkImage> scratchImg(new Image(TextureProxyView(texture, imgSwizzle), colorInfo));
742
743 SkISize srcSize = texture->dimensions();
744 const SkColorInfo outColorInfo = colorInfo.makeAlphaType(kPremul_SkAlphaType);
745
746 // Alternate between two scratch surfaces to avoid reading from and writing to a texture in the
747 // same pass. The dimensions of the first usages of the two scratch textures will be 1/2 and 1/4
748 // those of the original texture, respectively.
749 sk_sp<Surface> scratchSurfaces[2];
750 for (int i = 0; i < 2; ++i) {
751 scratchSurfaces[i] = make_renderable_scratch_surface(
752 recorder,
753 SkImageInfo::Make(SkISize::Make(std::max(1, srcSize.width() >> (i + 1)),
754 std::max(1, srcSize.height() >> (i + 1))),
755 outColorInfo),
757 "GenerateMipmapsScratchTexture");
758 if (!scratchSurfaces[i]) {
759 return false;
760 }
761 }
762
763 for (int mipLevel = 1; srcSize.width() > 1 || srcSize.height() > 1; ++mipLevel) {
764 const SkISize dstSize = SkISize::Make(std::max(srcSize.width() >> 1, 1),
765 std::max(srcSize.height() >> 1, 1));
766
767 Surface* scratchSurface = scratchSurfaces[(mipLevel - 1) & 1].get();
768
770 paint.setBlendMode(SkBlendMode::kSrc);
771 scratchSurface->getCanvas()->drawImageRect(scratchImg,
772 SkRect::Make(srcSize),
773 SkRect::Make(dstSize),
774 kSamplingOptions,
775 &paint,
777
778 // Make sure the rescaling draw finishes before copying the results.
779 Flush(scratchSurface);
780
782 static_cast<const Surface*>(scratchSurface)->readSurfaceView().refProxy(),
783 SkIRect::MakeSize(dstSize),
784 texture,
785 {0, 0},
786 mipLevel);
787 if (!copyTask) {
788 return false;
789 }
790 recorder->priv().add(std::move(copyTask));
791
792 scratchImg = scratchSurface->asImage();
793 srcSize = dstSize;
794 }
795
796 return true;
797}
798
799std::pair<sk_sp<SkImage>, SkSamplingOptions> GetGraphiteBacked(Recorder* recorder,
800 const SkImage* imageIn,
804
805 if (imageIn->dimensions().area() <= 1 && mipmapped == Mipmapped::kYes) {
806 mipmapped = Mipmapped::kNo;
808 }
809
811 if (as_IB(imageIn)->isGraphiteBacked()) {
812 result = sk_ref_sp(imageIn);
813
814 // If the preexisting Graphite-backed image doesn't have the required mipmaps we will drop
815 // down the sampling
816 if (mipmapped == Mipmapped::kYes && !result->hasMipmaps()) {
817 mipmapped = Mipmapped::kNo;
819 }
820 } else {
821 auto clientImageProvider = recorder->clientImageProvider();
822 result = clientImageProvider->findOrCreate(
823 recorder, imageIn, {mipmapped == Mipmapped::kYes});
824
825 if (!valid_client_provided_image(
826 result.get(), imageIn, {mipmapped == Mipmapped::kYes})) {
827 // The client did not fulfill the ImageProvider contract so drop the image.
828 result = nullptr;
829 }
830 }
831
832 if (sampling.isAniso() && result) {
834 }
835
836 return { result, sampling };
837}
838
840 if (!image) {
841 return {};
842 }
843 if (!as_IB(image)->isGraphiteBacked()) {
844 return {};
845 }
846 // A YUVA image (even if backed by graphite textures) is not a single texture
847 if (as_IB(image)->isYUVA()) {
848 return {};
849 }
850
851 auto gi = reinterpret_cast<const Image*>(image);
852 return gi->textureProxyView();
853}
854
856 // GPU compute coverage mask renderers need to bind the mask texture as a storage binding, which
857 // support a limited set of color formats. In general, we use RGBA8 if Alpha8 can't be
858 // supported.
861 }
863}
864
865} // namespace skgpu::graphite
866
867namespace skif {
868
869namespace {
870
871// TODO(michaelludwig): The skgpu::BlurUtils effects will be migrated to src/core to implement a
872// shader BlurEngine that can be shared by rastr, Ganesh, and Graphite. This is blocked by having
873// skif::FilterResult handle the resizing to the max supported sigma.
874class GraphiteBackend :
875 public Backend,
876#if defined(SK_USE_LEGACY_BLUR_GRAPHITE)
878#else
879 private SkShaderBlurAlgorithm,
880#endif
881 private SkBlurEngine {
882public:
883
884 GraphiteBackend(skgpu::graphite::Recorder* recorder,
885 const SkSurfaceProps& surfaceProps,
887 : Backend(SkImageFilterCache::Create(SkImageFilterCache::kDefaultTransientSize),
888 surfaceProps, colorType)
889 , fRecorder(recorder) {}
890
891 // Backend
892 sk_sp<SkDevice> makeDevice(SkISize size,
893 sk_sp<SkColorSpace> colorSpace,
894 const SkSurfaceProps* props) const override {
896 this->colorType(),
897 kPremul_SkAlphaType,
898 std::move(colorSpace));
899 return skgpu::graphite::Device::Make(fRecorder,
900 imageInfo,
904 props ? *props : this->surfaceProps(),
906 "ImageFilterResult");
907 }
908
909 sk_sp<SkSpecialImage> makeImage(const SkIRect& subset, sk_sp<SkImage> image) const override {
910 return SkSpecialImages::MakeGraphite(fRecorder, subset, image, this->surfaceProps());
911 }
912
913 sk_sp<SkImage> getCachedBitmap(const SkBitmap& data) const override {
915 "ImageFilterCachedBitmap");
916 if (!proxy) {
917 return nullptr;
918 }
919
920 const SkColorInfo& colorInfo = data.info().colorInfo();
921 skgpu::Swizzle swizzle = fRecorder->priv().caps()->getReadSwizzle(colorInfo.colorType(),
922 proxy->textureInfo());
923 return sk_make_sp<skgpu::graphite::Image>(
924 skgpu::graphite::TextureProxyView(std::move(proxy), swizzle),
925 colorInfo);
926 }
927
928 const SkBlurEngine* getBlurEngine() const override { return this; }
929
930 // SkBlurEngine
931 const SkBlurEngine::Algorithm* findAlgorithm(SkSize sigma,
932 SkColorType colorType) const override {
933 // The runtime effect blurs handle all tilemodes and color types
934 return this;
935 }
936
937#if defined(SK_USE_LEGACY_BLUR_GRAPHITE)
938 // SkBlurEngine::Algorithm
939 float maxSigma() const override {
940 return SK_ScalarInfinity;
941 }
942
943 bool supportsOnlyDecalTiling() const override { return false; }
944
945 sk_sp<SkSpecialImage> blur(SkSize sigma,
947 const SkIRect& srcRect,
948 SkTileMode tileMode,
949 const SkIRect& dstRect) const override {
950 TRACE_EVENT_INSTANT2("skia.gpu", "GaussianBlur", TRACE_EVENT_SCOPE_THREAD,
951 "sigmaX", sigma.width(), "sigmaY", sigma.height());
952
953 SkColorSpace* cs = src->getColorSpace();
954 return skgpu::graphite::blur_impl(fRecorder, sigma, std::move(src), srcRect, tileMode,
955 dstRect, sk_ref_sp(cs), this->surfaceProps());
956 }
957#else
958 bool useLegacyFilterResultBlur() const override { return false; }
959
960 // SkShaderBlurAlgorithm
961 sk_sp<SkDevice> makeDevice(const SkImageInfo& imageInfo) const override {
962 return skgpu::graphite::Device::Make(fRecorder,
963 imageInfo,
967 this->surfaceProps(),
969 "EvalBlurTexture");
970 }
971
972#endif
973
974private:
975 skgpu::graphite::Recorder* fRecorder;
976};
977
978} // anonymous namespace
979
981 const SkSurfaceProps& surfaceProps,
983 SkASSERT(recorder);
984 return sk_make_sp<GraphiteBackend>(recorder, surfaceProps, colorType);
985}
986
987} // namespace skif
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
#define SKGPU_LOG_E(fmt,...)
Definition: Log.h:38
#define SKGPU_LOG_W(fmt,...)
Definition: Log.h:40
static sk_sp< Effect > Create()
Definition: RefCntTest.cpp:117
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
Definition: SkAlphaType.h:29
#define SkASSERT(cond)
Definition: SkAssert.h:116
SkBackingFit
Definition: SkBackingFit.h:16
SkColorType
Definition: SkColorType.h:19
@ kAlpha_8_SkColorType
pixel with alpha in 8-bit byte
Definition: SkColorType.h:21
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
Definition: SkColorType.h:24
@ kUnknown_SkColorType
uninitialized
Definition: SkColorType.h:20
size_t SkCompressedFormatDataSize(SkTextureCompressionType compressionType, SkISize dimensions, bool mipmapped)
#define sk_float_ceil2int(x)
static SkColorType colorType(AImageDecoder *decoder, const AImageDecoderHeaderInfo *headerInfo)
static uint32_t SkColorTypeChannelFlags(SkColorType ct)
static bool SkColorTypeIsAlphaOnly(SkColorType ct)
static bool SkImageInfoIsValid(const SkImageInfo &info)
static SkImage_Base * as_IB(SkImage *image)
Definition: SkImage_Base.h:201
sk_sp< T > sk_ref_sp(T *obj)
Definition: SkRefCnt.h:381
#define SK_ScalarInfinity
Definition: SkScalar.h:26
SkTextureCompressionType
SkTileMode
Definition: SkTileMode.h:13
static constexpr bool SkToBool(const T &x)
Definition: SkTo.h:35
#define TRACE_EVENT_SCOPE_THREAD
#define TRACE_FUNC
Definition: SkTraceEvent.h:30
void setImmutable()
Definition: SkBitmap.cpp:400
SkISize dimensions() const
Definition: SkBitmap.h:388
const SkPixmap & pixmap() const
Definition: SkBitmap.h:133
size_t rowBytes() const
Definition: SkBitmap.h:238
SkColorType colorType() const
Definition: SkBitmap.h:160
void * getPixels() const
Definition: SkBitmap.h:283
const SkImageInfo & info() const
Definition: SkBitmap.h:139
bool tryAllocPixels(const SkImageInfo &info, size_t rowBytes)
Definition: SkBitmap.cpp:271
@ kStrict_SrcRectConstraint
sample only inside bounds; slower
Definition: SkCanvas.h:1542
void drawImageRect(const SkImage *, const SkRect &src, const SkRect &dst, const SkSamplingOptions &, const SkPaint *, SrcRectConstraint)
Definition: SkCanvas.cpp:2333
SkColorInfo makeAlphaType(SkAlphaType newAlphaType) const
Definition: SkImageInfo.cpp:76
SkColorInfo makeColorType(SkColorType newColorType) const
Definition: SkImageInfo.cpp:80
SkColorType colorType() const
Definition: SkImageInfo.h:140
bool gammaIsLinear() const
sk_sp< SkColorSpace > makeLinearGamma() const
const SkImageInfo & imageInfo() const
Definition: SkImage.h:279
SkISize dimensions() const
Definition: SkImage.h:297
SkAlphaType alphaType() const
Definition: SkImage.cpp:154
RescaleMode
Definition: SkImage.h:587
RescaleGamma
Definition: SkImage.h:585
SkColorType colorType() const
Definition: SkImage.cpp:152
static SkM44 Translate(SkScalar x, SkScalar y, SkScalar z=0)
Definition: SkM44.h:225
static SkMatrix Translate(SkScalar dx, SkScalar dy)
Definition: SkMatrix.h:91
static SkMipmap * Build(const SkPixmap &src, SkDiscardableFactoryProc, bool computeContents=true)
Definition: SkMipmap.cpp:45
int countLevels() const
Definition: SkMipmap.cpp:276
bool getLevel(int index, Level *) const
Definition: SkMipmap.cpp:280
static int ComputeLevelCount(int baseWidth, int baseHeight)
Definition: SkMipmap.cpp:134
size_t rowBytes() const
Definition: SkPixmap.h:145
SkColorType colorType() const
Definition: SkPixmap.h:173
const void * addr() const
Definition: SkPixmap.h:153
static SkSamplingOptions AnisoFallback(bool imageIsMipped)
int width() const
virtual sk_sp< SkImage > asImage() const =0
sk_sp< SkSpecialImage > makeSubset(const SkIRect &subset) const
int height() const
const SkIRect & subset() const
virtual sk_sp< SkShader > asShader(SkTileMode, const SkSamplingOptions &, const SkMatrix &lm, bool strict=true) const
SkColorType colorType() const
SkCanvas * getCanvas()
Definition: SkSurface.cpp:82
virtual SkImageInfo imageInfo() const
Definition: SkSurface.h:188
static sk_sp< RefCntedCallback > Make(Callback proc, Context ctx)
static constexpr Swizzle Concat(const Swizzle &a, const Swizzle &b)
Definition: Swizzle.h:156
skgpu::Swizzle getReadSwizzle(SkColorType, const TextureInfo &) const
Definition: Caps.cpp:129
bool isTexturable(const TextureInfo &) const
Definition: Caps.cpp:66
virtual TextureInfo getDefaultStorageTextureInfo(SkColorType) const =0
virtual bool isStorage(const TextureInfo &) const =0
SkColorType getRenderableColorType(SkColorType) const
Definition: Caps.cpp:114
virtual TextureInfo getDefaultSampledTextureInfo(SkColorType, Mipmapped mipmapped, Protected, Renderable) const =0
bool areColorTypeAndTextureInfoCompatible(SkColorType, const TextureInfo &) const
Definition: Caps.cpp:85
static sk_sp< CopyTextureToTextureTask > Make(sk_sp< TextureProxy > srcProxy, SkIRect srcRect, sk_sp< TextureProxy > dstProxy, SkIPoint dstPoint, int dstLevel=0)
Definition: CopyTask.cpp:123
static sk_sp< Device > Make(Recorder *recorder, sk_sp< TextureProxy >, SkISize deviceSize, const SkColorInfo &, const SkSurfaceProps &, LoadOp initialLoadOp, bool registerWithRecorder=true)
Definition: Device.cpp:276
const TextureProxyView & textureProxyView() const
Protected isProtected() const
Definition: RecorderPriv.h:52
const Caps * caps() const
Definition: RecorderPriv.h:31
ResourceProvider * resourceProvider()
Definition: RecorderPriv.h:33
static sk_sp< TextureProxy > CreateCachedProxy(Recorder *, const SkBitmap &, std::string_view label)
Definition: Recorder.cpp:544
void add(sk_sp< Task >)
Definition: Recorder.cpp:485
ImageProvider * clientImageProvider()
Definition: Recorder.h:88
sk_sp< Image > asImage() const
static sk_sp< Surface > MakeScratch(Recorder *recorder, const SkImageInfo &info, std::string_view label, Budgeted budgeted=Budgeted::kYes, Mipmapped mipmapped=Mipmapped::kNo, SkBackingFit backingFit=SkBackingFit::kApprox)
static sk_sp< TextureProxy > Make(const Caps *, ResourceProvider *, SkISize dimensions, const TextureInfo &, std::string_view label, skgpu::Budgeted)
const TextureInfo & textureInfo() const
Definition: TextureProxy.h:38
static sk_sp< TextureProxy > MakeLazy(const Caps *, SkISize dimensions, const TextureInfo &, skgpu::Budgeted, Volatile, LazyInstantiateCallback &&)
static UploadInstance Make(Recorder *, sk_sp< TextureProxy > targetProxy, const SkColorInfo &srcColorInfo, const SkColorInfo &dstColorInfo, SkSpan< const MipLevel > levels, const SkIRect &dstRect, std::unique_ptr< ConditionalUploadContext >)
Definition: UploadTask.cpp:91
static sk_sp< UploadTask > Make(UploadList *)
Definition: UploadTask.cpp:425
const Paint & paint
Definition: color_source.cc:38
VkDevice device
Definition: main.cc:53
VkSurfaceKHR surface
Definition: main.cc:49
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
GAsyncResult * result
static float max(float r, float g, float b)
Definition: hsl.cpp:49
static float min(float r, float g, float b)
Definition: hsl.cpp:48
FlTexture * texture
void * GraphitePromiseTextureFulfillContext
Definition: Image.h:41
std::tuple< skgpu::graphite::BackendTexture, GraphitePromiseTextureReleaseContext >(*)(GraphitePromiseTextureFulfillContext) GraphitePromiseTextureFulfillProc
Definition: Image.h:47
void(*)(GraphitePromiseTextureReleaseContext) GraphitePromiseTextureReleaseProc
Definition: Image.h:49
sk_sp< const SkImage > image
Definition: SkRecords.h:269
SkSamplingOptions sampling
Definition: SkRecords.h:337
sk_sp< SkSpecialImage > MakeGraphite(skgpu::graphite::Recorder *recorder, const SkIRect &subset, sk_sp< SkImage > image, const SkSurfaceProps &props)
SK_API sk_sp< SkImage > AsImage(sk_sp< const SkSurface >)
Definition: bitmap.py:1
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace Enable an endless trace buffer The default is a ring buffer This is useful when very old events need to viewed For during application launch Memory usage will continue to grow indefinitely however Start app with an specific route defined on the framework flutter assets dir
Definition: switches.h:145
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
CanvasImage Image
Definition: dart_ui.cc:55
dst
Definition: cp.py:12
list offsets
Definition: mskp_parser.py:37
const myers::Point & get(const myers::Segment &)
bool GenerateMipmaps(Recorder *recorder, sk_sp< TextureProxy > texture, const SkColorInfo &colorInfo)
SkColorType ComputeShaderCoverageMaskTargetFormat(const Caps *caps)
sk_sp< SkImage > RescaleImage(Recorder *recorder, const SkImage *srcImage, SkIRect srcIRect, const SkImageInfo &dstInfo, SkImage::RescaleGamma rescaleGamma, SkImage::RescaleMode rescaleMode)
void Flush(sk_sp< SkSurface > surface)
sk_sp< TextureProxy > MakePromiseImageLazyProxy(const Caps *caps, SkISize dimensions, TextureInfo textureInfo, Volatile isVolatile, sk_sp< RefCntedCallback > releaseHelper, GraphitePromiseTextureFulfillProc fulfillProc, GraphitePromiseTextureFulfillContext fulfillContext, GraphitePromiseTextureReleaseProc textureReleaseProc, std::string_view label)
sk_sp< SkImage > MakeFromBitmap(Recorder *recorder, const SkColorInfo &colorInfo, const SkBitmap &bitmap, sk_sp< SkMipmap > mipmaps, Budgeted budgeted, SkImage::RequiredProperties requiredProps, std::string_view label)
std::pair< sk_sp< SkImage >, SkSamplingOptions > GetGraphiteBacked(Recorder *recorder, const SkImage *imageIn, SkSamplingOptions sampling)
size_t ComputeSize(SkISize dimensions, const TextureInfo &info)
std::tuple< TextureProxyView, SkColorType > MakeBitmapProxyView(Recorder *recorder, const SkBitmap &bitmap, sk_sp< SkMipmap > mipmapsIn, Mipmapped mipmapped, Budgeted budgeted, std::string_view label)
TextureProxyView AsView(const SkImage *image)
sk_sp< Image > CopyAsDraw(Recorder *recorder, const SkImage *image, const SkIRect &subset, const SkColorInfo &dstColorInfo, Budgeted budgeted, Mipmapped mipmapped, SkBackingFit backingFit, std::string_view label)
static constexpr int kMaxBlurSamples
Definition: BlurUtils.h:35
static constexpr float kMaxLinearBlurSigma
Definition: BlurUtils.h:36
Budgeted
Definition: GpuTypes.h:35
void Compute2DBlurOffsets(SkISize radius, std::array< SkV4, kMaxBlurSamples/2 > &offsets)
Definition: BlurUtils.h:60
Mipmapped
Definition: GpuTypes.h:53
const SkRuntimeEffect * GetLinearBlur1DEffect(int radius)
Definition: BlurUtils.h:42
int BlurSigmaRadius(float sigma)
Definition: BlurUtils.h:33
constexpr int BlurKernelWidth(int radius)
Definition: BlurUtils.h:26
void Compute2DBlurKernel(SkSize sigma, SkISize radius, SkSpan< float > kernel)
Definition: BlurUtils.h:46
const SkRuntimeEffect * GetBlur2DEffect(const SkISize &radii)
Definition: BlurUtils.h:38
void Compute1DBlurLinearKernel(float sigma, int radius, std::array< SkV4, kMaxBlurSamples/2 > &offsetsAndKernel)
Definition: BlurUtils.h:64
Protected
Definition: GpuTypes.h:61
SkSamplingOptions(SkFilterMode::kLinear))
Definition: SkDevice.h:63
sk_sp< Backend > MakeGraphiteBackend(skgpu::graphite::Recorder *recorder, const SkSurfaceProps &surfaceProps, SkColorType colorType)
Definition: ref_ptr.h:256
Definition: upload.py:1
static constexpr SkCubicResampler CatmullRom()
Definition: SkRect.h:32
SkIRect makeOutset(int32_t dx, int32_t dy) const
Definition: SkRect.h:350
bool intersect(const SkIRect &r)
Definition: SkRect.h:513
constexpr int32_t top() const
Definition: SkRect.h:120
constexpr SkISize size() const
Definition: SkRect.h:172
constexpr int32_t height() const
Definition: SkRect.h:165
static constexpr SkIRect MakeSize(const SkISize &size)
Definition: SkRect.h:66
constexpr int32_t width() const
Definition: SkRect.h:158
void offset(int32_t dx, int32_t dy)
Definition: SkRect.h:367
constexpr SkIRect makeOffset(int32_t dx, int32_t dy) const
Definition: SkRect.h:300
static constexpr SkIRect MakeWH(int32_t w, int32_t h)
Definition: SkRect.h:56
constexpr SkIPoint topLeft() const
Definition: SkRect.h:151
void outset(int32_t dx, int32_t dy)
Definition: SkRect.h:428
constexpr int32_t left() const
Definition: SkRect.h:113
Definition: SkSize.h:16
bool isEmpty() const
Definition: SkSize.h:31
static constexpr SkISize Make(int32_t w, int32_t h)
Definition: SkSize.h:20
int32_t fHeight
Definition: SkSize.h:18
int32_t fWidth
Definition: SkSize.h:17
constexpr int32_t width() const
Definition: SkSize.h:36
constexpr int32_t height() const
Definition: SkSize.h:37
constexpr int64_t area() const
Definition: SkSize.h:39
const SkColorInfo & colorInfo() const
Definition: SkImageInfo.h:404
SkImageInfo makeAlphaType(SkAlphaType newAlphaType) const
Definition: SkImageInfo.h:466
SkImageInfo makeDimensions(SkISize newSize) const
Definition: SkImageInfo.h:454
SkColorSpace * colorSpace() const
SkISize dimensions() const
Definition: SkImageInfo.h:421
int width() const
Definition: SkImageInfo.h:365
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)
SkColorType colorType() const
Definition: SkImageInfo.h:373
int height() const
Definition: SkImageInfo.h:371
SkPixmap fPixmap
Definition: SkMipmap.h:71
static SkRect Make(const SkISize &size)
Definition: SkRect.h:669
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
Definition: SkRect.h:659
void roundOut(SkIRect *dst) const
Definition: SkRect.h:1241
constexpr float height() const
Definition: SkRect.h:769
constexpr float width() const
Definition: SkRect.h:762
const SkMipmapMode mipmap
Definition: SkSize.h:52
SkScalar width() const
Definition: SkSize.h:76
SkScalar height() const
Definition: SkSize.h:77
Definition: SkM44.h:19
Definition: SkM44.h:98
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63
#define TRACE_EVENT0(category_group, name)
Definition: trace_event.h:131
#define TRACE_EVENT_INSTANT2(category_group, name, arg1_name, arg1_val, arg2_name, arg2_val)
Definition: trace_event.h:184