75#include <unordered_map>
83#if defined(GRAPHITE_TEST_UTILS)
84int gOverrideMaxTextureSizeGraphite = 0;
89std::atomic<int> gNumTilesDrawnGraphite{0};
94#define ASSERT_SINGLE_OWNER SkASSERT(fRecorder); SKGPU_ASSERT_SINGLE_OWNER(fRecorder->singleOwner())
103bool blender_depends_on_dst(
const SkBlender* blender,
bool srcIsTransparent) {
105 if (!bm.has_value()) {
114 return srcIsTransparent;
125 const bool srcIsTransparent = !
color.isOpaque() || (shader && !shader->
isOpaque()) ||
128 if (primitiveBlender && blender_depends_on_dst(primitiveBlender, srcIsTransparent)) {
132 return blender_depends_on_dst(finalBlender, srcIsTransparent);
135bool paint_depends_on_dst(
const PaintParams& paintParams) {
136 return paint_depends_on_dst(paintParams.color(),
137 paintParams.shader(),
138 paintParams.colorFilter(),
139 paintParams.finalBlender(),
140 paintParams.primitiveBlender());
146 return paint_depends_on_dst(
paint.getColor4f(),
148 paint.getColorFilter(),
154std::optional<SkColor4f> extract_paint_color(
const SkPaint&
paint,
157 if (
paint.getShader()) {
165 return filter->filterColor4f(dstPaintColor, dstCS, dstCS);
167 return dstPaintColor;
170SkIRect rect_to_pixelbounds(
const Rect& r) {
171 return r.makeRoundOut().asSkIRect();
198 auto& trees = fTrees[drawOrder];
200 for (
auto&& tree : trees) {
201 if (tree->add(rect)) {
204 stencil = stencil.
next();
210 trees.push_back(newTree);
224 IntersectionTree* makeTree() {
225 return fTreeStore.make<IntersectionTree>();
233 std::unordered_map<CompressedPaintersOrder, std::vector<IntersectionTree*>, Hash> fTrees;
244 bool registerWithRecorder) {
260 backingDimensions, textureInfo, budgeted),
265 registerWithRecorder);
274 bool registerWithRecorder) {
293 if (registerWithRecorder) {
318 :
SkDevice(dc->imageInfo(), dc->surfaceProps())
319 SkDEBUGCODE(, fPreRecorderSentinel(reinterpret_cast<intptr_t>(recorder) - 1))
320 , fRecorder(recorder)
321 SkDEBUGCODE(, fPostRecorderSentinel(reinterpret_cast<intptr_t>(recorder) + 1))
326 , fDisjointStencilSet(
std::make_unique<IntersectionTreeSet>())
327 , fCachedLocalToDevice(
SkM44())
329 , fSDFTControl(recorder->
priv().caps()->getSDFTControl(false)) {
331 if (fRecorder->priv().caps()->defaultMSAASamplesCount() > 1) {
332 if (fRecorder->priv().caps()->msaaRenderToSingleSampledSupport()) {
333 fMSAASupported =
true;
336 fRecorder->priv().caps()->getDefaultMSAATextureInfo(fDC->target()->textureInfo(),
338 fMSAASupported = msaaTexInfo.
isValid();
349 SkASSERT(!fRecorder || fScopedRecordingID != 0);
351 if (fScopedRecordingID != 0 && fRecorder) {
352 SkASSERT(fScopedRecordingID == fRecorder->priv().nextRecordingID());
359void Device::setImmutable() {
366 this->flushPendingWorkToRecorder();
367 fRecorder->deregisterDevice(
this);
370 this->abandonRecorder();
375 if (this->checkLocalToDeviceDirty()) {
376 fCachedLocalToDevice =
Transform{this->localToDevice44()};
378 return fCachedLocalToDevice;
382 return {this->surfaceProps(), this->scalerContextFlags(), &fSDFTControl};
392 LoadOp initialLoadOp =
info.fInfo.isOpaque() ? LoadOp::kDiscard : LoadOp::kClear;
394 return Make(fRecorder,
398#
if defined(GRAPHITE_USE_APPROX_FIT_FOR_FILTERS)
416 this->flushPendingWorkToRecorder();
418 const SkColorInfo& colorInfo = this->imageInfo().colorInfo();
423 Swizzle readSwizzle = fRecorder->priv().caps()->getReadSwizzle(
424 colorInfo.
colorType(), this->target()->textureInfo());
427 return Image::Copy(fRecorder, srcView, colorInfo, subset, budgeted, mipmapped, backingFit);
430bool Device::onReadPixels(
const SkPixmap& pm,
int srcX,
int srcY) {
431#if defined(GRAPHITE_TEST_UTILS)
435 if (
Context* context = fRecorder->
priv().context()) {
439 std::unique_ptr<Recording> recording = fRecorder->snap();
445 if (!context->insertRecording(
info)) {
448 return context->
priv().readPixels(pm, fDC->target(), this->imageInfo(), srcX, srcY);
455bool Device::onWritePixels(
const SkPixmap& src,
int x,
int y) {
476 if (!fRecorder->priv().caps()->supportsWritePixels(
target->textureInfo())) {
503 const void* addr = src.addr(dstRect.
fLeft -
x, dstRect.
fTop -
y);
504 std::vector<MipLevel> levels;
505 levels.push_back({addr, src.rowBytes()});
509 this->internalFlush();
513 return fDC->recordUpload(fRecorder, fDC->refTarget(), src.info().colorInfo(),
514 this->imageInfo().colorInfo(), levels, dstRect,
nullptr);
520bool Device::isClipAntiAliased()
const {
523 if (
type == ClipStack::ClipState::kWideOpen ||
type == ClipStack::ClipState::kEmpty) {
525 }
else if (
type == ClipStack::ClipState::kDeviceRect) {
527 SkASSERT(rect.fShape.isRect() && rect.fLocalToDevice.type() == Transform::Type::kIdentity);
528 return rect.fShape.rect() != rect.fShape.rect().makeRoundOut();
535 return rect_to_pixelbounds(fClip.conservativeBounds());
539void Device::android_utils_clipAsRgn(
SkRegion* region)
const {
540 SkIRect bounds = this->devClipBounds();
543 const SkRegion deviceBounds(bounds);
546 if (e.fShape.isRect() && e.fLocalToDevice.type() == Transform::Type::kIdentity) {
547 tmp.
setRect(rect_to_pixelbounds(e.fShape.rect()));
549 SkPath tmpPath = e.fShape.asPath();
551 tmp.
setPath(tmpPath, deviceBounds);
561 fClip.clipShape(this->localToDeviceTransform(),
Shape{rect}, op);
568 fClip.clipShape(this->localToDeviceTransform(),
Shape{rrect}, op);
576 fClip.clipShape(this->localToDeviceTransform(),
Shape{path}, op);
580 fClip.clipShader(std::move(shader));
587 Transform globalToDevice{this->globalToDevice()};
590 fClip.clipShape(globalToDevice,
Shape{}, op);
591 }
else if (globalRgn.
isRect()) {
599 fClip.clipShape(globalToDevice,
Shape{path}, op);
603void Device::replaceClip(
const SkIRect& rect) {
625 if (this->isClipWideOpen() && !fDC->target()->isFullyLazy()) {
626 if (!paint_depends_on_dst(
paint)) {
627 if (std::optional<SkColor4f>
color = extract_paint_color(
paint, fDC->colorInfo())) {
639 const Transform& localToDevice = this->localToDeviceTransform();
640 if (!localToDevice.
valid()) {
648 this->drawGeometry(localToDevice,
652 DrawFlags::kIgnorePathEffect);
656 this->drawGeometry(this->localToDeviceTransform(),
Geometry(
Shape(r)),
663 this->drawGeometry(this->localToDeviceTransform(),
667 DrawFlags::kIgnorePathEffect,
689 size_t cacheSize = recorder->priv().getResourceCacheLimit();
690 size_t maxTextureSize = recorder->priv().caps()->maxTextureSize();
692#if defined(GRAPHITE_TEST_UTILS)
693 if (gOverrideMaxTextureSizeGraphite) {
694 maxTextureSize = gOverrideMaxTextureSizeGraphite;
696 gNumTilesDrawnGraphite.store(0, std::memory_order_relaxed);
699 [[maybe_unused]]
auto [wasTiled, numTiles] =
710#if defined(GRAPHITE_TEST_UTILS)
711 gNumTilesDrawnGraphite.store(numTiles, std::memory_order_relaxed);
717 if (
paint.getPathEffect()) {
731 this->drawGeometry(this->localToDeviceTransform(),
Geometry(
Shape(rr)),
738 this->drawGeometry(this->localToDeviceTransform(),
Geometry(
Shape(path)),
752 paint.getStrokeJoin(),
753 paint.getStrokeMiter());
761 for (
size_t i = 0; i <
count; i += inc) {
762 this->drawGeometry(this->localToDeviceTransform(),
768void Device::drawEdgeAAQuad(
const SkRect& rect,
779 this->drawGeometry(this->localToDeviceTransform(),
783 DrawFlags::kIgnorePathEffect);
793 int dstClipIndex = 0;
794 for (
int i = 0; i <
count; ++i) {
796 SkASSERT(!set[i].fHasClip || dstClips);
798 SkASSERT(set[i].fMatrixIndex < 0 || preViewMatrices);
800 auto [ imageToDraw, newSampling ] =
803 SKGPU_LOG_W(
"Device::drawImageRect: Creation of Graphite-backed image failed");
812 imageToDraw.get(), newSampling, set[i].fSrcRect, set[i].fDstRect,
828 if (set[i].fMatrixIndex < 0) {
829 this->drawGeometry(this->localToDeviceTransform(),
833 DrawFlags::kIgnorePathEffect);
835 SkM44 xtraTransform(preViewMatrices[set[i].fMatrixIndex]);
836 this->drawGeometry(this->localToDeviceTransform().concat(xtraTransform),
840 DrawFlags::kIgnorePathEffect);
843 dstClipIndex += 4 * set[i].fHasClip;
855 this->drawEdgeAAImageSet(&single, 1,
nullptr,
nullptr, sampling,
paint, constraint);
864 this->drawAtlasSubRun(subRun, drawOrigin,
paint, subRunStorage, rendererData);
872 fRecorder->priv().textBlobCache()->drawGlyphRunList(canvas,
873 this->localToDevice(),
876 this->strikeDeviceInfo(),
877 this->atlasDelegate());
893 return glyphs->regenerateAtlasForGraphite(
begin,
end, maskFormat, padding, fRecorder);
895 for (
int subRunCursor = 0; subRunCursor < subRunEnd;) {
903 if (glyphsRegenerated) {
905 this->localToDeviceTransform(), drawOrigin);
908 if (subRun->
maskFormat() == skgpu::MaskFormat::kARGB) {
912 this->drawGeometry(localToDevice,
913 Geometry(SubRunData(subRun,
916 this->localToDeviceTransform().inverse(),
923 DrawFlags::kIgnorePathEffect);
925 subRunCursor += glyphsRegenerated;
927 if (subRunCursor < subRunEnd) {
933 fRecorder->priv().flushTrackedDevices();
938void Device::drawGeometry(
const Transform& localToDevice,
939 const Geometry& geometry,
944 bool skipColorXform) {
947 if (!localToDevice.valid()) {
949 SKGPU_LOG_W(
"Skipping draw with non-invertible/non-finite transform.");
955 if (!(
flags & DrawFlags::kIgnorePathEffect) &&
paint.getPathEffect()) {
965 float maxScaleFactor = localToDevice.maxScaleFactor();
966 if (localToDevice.type() == Transform::Type::kPerspective) {
967 auto bounds = geometry.bounds();
968 float tl = std::get<1>(localToDevice.scaleFactors({bounds.left(), bounds.top()}));
969 float tr = std::get<1>(localToDevice.scaleFactors({bounds.right(), bounds.top()}));
970 float br = std::get<1>(localToDevice.scaleFactors({bounds.right(), bounds.bot()}));
971 float bl = std::get<1>(localToDevice.scaleFactors({bounds.left(), bounds.bot()}));
972 maxScaleFactor = std::max(std::max(tl, tr), std::max(bl, br));
976 if (
paint.getPathEffect()->filterPath(&dst, geometry.shape().asPath(), &newStyle,
977 nullptr, localToDevice)) {
978 dst.setIsVolatile(
true);
980 this->drawGeometry(localToDevice, Geometry(
Shape(dst)),
paint, newStyle,
981 flags | DrawFlags::kIgnorePathEffect, std::move(primitiveBlender),
985 SKGPU_LOG_W(
"Path effect failed to apply, drawing original path.");
986 this->drawGeometry(localToDevice, geometry,
paint, style,
987 flags | DrawFlags::kIgnorePathEffect, std::move(primitiveBlender),
996 if (geometry.isShape() && localToDevice.type() == Transform::Type::kPerspective &&
997 !is_simple_shape(geometry.shape(), style.
getStyle())) {
998 SkPath devicePath = geometry.shape().asPath();
999 devicePath.
transform(localToDevice.matrix().asM33());
1001 this->drawGeometry(Transform::Identity(), Geometry(
Shape(devicePath)),
paint, style,
flags,
1002 std::move(primitiveBlender), skipColorXform);
1022 this->chooseRenderer(localToDevice, geometry, style,
false);
1023 if (!renderer && !pathAtlas) {
1024 SKGPU_LOG_W(
"Skipping draw with no supported renderer or PathAtlas.");
1030 const bool outsetBoundsForAA =
renderer ?
renderer->outsetBoundsForAA() :
true;
1031 ClipStack::ElementList clipElements;
1033 fClip.visitClipStackForDraw(localToDevice, geometry, style, outsetBoundsForAA,
1035 if (
clip.isClippedOut()) {
1043 const std::optional<SkBlendMode> blendMode = blender ? blender->
asBlendMode()
1046 : Coverage::kSingleChannel;
1052 const int numNewRenderSteps =
1055 ? fRecorder->priv().rendererProvider()->tessellatedStrokes()->numRenderSteps()
1061 const bool needsFlush = this->needsFlushBeforeDraw(numNewRenderSteps, dstReadReq);
1063 if (pathAtlas !=
nullptr) {
1066 fRecorder->priv().flushTrackedDevices();
1068 this->flushPendingWorkToRecorder();
1074 std::optional<PathAtlas::MaskAndOrigin> atlasMask;
1075 if (pathAtlas !=
nullptr) {
1076 std::tie(renderer, atlasMask) = pathAtlas->addShape(
clip.transformedShapeBounds(),
1084 if (!atlasMask && !needsFlush) {
1087 fRecorder->priv().flushTrackedDevices();
1090 std::tie(renderer, atlasMask) = pathAtlas->addShape(
clip.transformedShapeBounds(),
1110 DrawOrder order(fCurrentDepth.next());
1112 clip, clipElements, fColorDepthBoundsManager.get(), order.depth());
1114#if defined(SK_DEBUG)
1122 auto dss =
step->depthStencilSettings();
1123 SkASSERT((!
step->performsShading() || dss.fDepthTestEnabled) &&
1124 (!dss.fDepthTestEnabled ||
1125 dss.fDepthCompareOp == CompareOp::kGreater ||
1126 dss.fDepthCompareOp == CompareOp::kGEqual));
1131 order.dependsOnPaintersOrder(clipOrder);
1136 if (!
renderer->emitsPrimitiveColor()) {
1137 primitiveBlender =
nullptr;
1138 }
else if (!
SkToBool(primitiveBlender)) {
1145 PaintParams shading{
paint,
1146 std::move(primitiveBlender),
1150 const bool dependsOnDst = rendererCoverage != Coverage::kNone || paint_depends_on_dst(shading);
1153 fColorDepthBoundsManager->getMostRecentDraw(
clip.drawBounds());
1154 order.dependsOnPaintersOrder(prevDraw);
1160 if (
renderer->depthStencilFlags() & DepthStencilFlags::kStencil) {
1163 order.dependsOnStencil(setIndex);
1168 shading.notifyImagesInUse(fRecorder, fDC.get());
1173 if (pathAtlas !=
nullptr) {
1176 auto [mask, origin] = *atlasMask;
1177 fDC->recordDraw(renderer, Transform::Translate(origin.fX, origin.fY), Geometry(mask),
1178 clip, order, &shading,
nullptr);
1187 ? fRecorder->priv().rendererProvider()->tessellatedStrokes()
1189 localToDevice, geometry,
clip, order, &shading, &stroke);
1193 fDC->recordDraw(renderer, localToDevice, geometry,
clip, order, &shading,
nullptr);
1205 fColorDepthBoundsManager->recordDraw(
clip.drawBounds(), order.paintOrder());
1206 fCurrentDepth = order.depth();
1214void Device::drawClipShape(
const Transform& localToDevice,
1220 Geometry geometry{shape};
1221 auto [
renderer, pathAtlas] = this->chooseRenderer(localToDevice,
1226 SKGPU_LOG_W(
"Skipping clip with no supported path renderer.");
1228 }
else if (
renderer->depthStencilFlags() & DepthStencilFlags::kStencil) {
1231 order.dependsOnStencil(setIndex);
1236 SkASSERT(fDC->pendingRenderSteps() +
renderer->numRenderSteps() < DrawList::kMaxRenderSteps);
1245 if (localToDevice.type() == Transform::Type::kPerspective) {
1246 SkPath devicePath = geometry.shape().asPath();
1247 devicePath.
transform(localToDevice.matrix().asM33());
1248 fDC->recordDraw(renderer, Transform::Identity(), Geometry(
Shape(devicePath)),
clip, order,
1251 fDC->recordDraw(renderer, localToDevice, geometry,
clip, order,
nullptr,
nullptr);
1255 if (order.depth() > fCurrentDepth) {
1256 fCurrentDepth = order.depth();
1262std::pair<const Renderer*, PathAtlas*> Device::chooseRenderer(
const Transform& localToDevice,
1263 const Geometry& geometry,
1265 bool requireMSAA)
const {
1266 const RendererProvider* renderers = fRecorder->priv().rendererProvider();
1270 if (geometry.isSubRun()) {
1273 if (!rendererData.
isSDF) {
1274 return {renderers->bitmapText(rendererData.
isLCD),
nullptr};
1276 return {renderers->sdfText(rendererData.
isLCD),
nullptr};
1277 }
else if (geometry.isVertices()) {
1279 return {renderers->vertices(
info.mode(),
info.hasColors(),
info.hasTexCoords()),
nullptr};
1280 }
else if (geometry.isCoverageMaskShape()) {
1284 return {renderers->coverageMask(),
nullptr};
1285 }
else if (geometry.isEdgeAAQuad()) {
1288 return {renderers->perEdgeAAQuad(),
nullptr};
1289 }
else if (geometry.isAnalyticBlur()) {
1290 return {renderers->analyticBlur(),
nullptr};
1291 }
else if (!geometry.isShape()) {
1293 return {
nullptr,
nullptr};
1296 const Shape& shape = geometry.shape();
1298 if (!requireMSAA && is_simple_shape(shape,
type)) {
1299 return {renderers->analyticRRect(),
nullptr};
1309#if defined(GRAPHITE_TEST_UTILS)
1315 PathAtlas* pathAtlas =
nullptr;
1320 AtlasProvider* atlasProvider = fRecorder->priv().atlasProvider();
1321 if (atlasProvider->isAvailable(AtlasProvider::PathAtlasFlags::kCompute) &&
1322 (strategy == PathRendererStrategy::kComputeAnalyticAA ||
1323 strategy == PathRendererStrategy::kComputeMSAA16 ||
1324 strategy == PathRendererStrategy::kComputeMSAA8 ||
1325 strategy == PathRendererStrategy::kDefault)) {
1326 pathAtlas = fDC->getComputePathAtlas(fRecorder);
1329 }
else if (atlasProvider->isAvailable(AtlasProvider::PathAtlasFlags::kRaster) &&
1330 (strategy == PathRendererStrategy::kRasterAA ||
1331 (strategy == PathRendererStrategy::kDefault && !fMSAASupported))) {
1332 pathAtlas = atlasProvider->getRasterPathAtlas();
1336 if (!requireMSAA && pathAtlas) {
1343 if (!fMSAASupported || strategy != PathRendererStrategy::kDefault) {
1344 return {
nullptr, pathAtlas};
1350 Rect drawBounds = localToDevice.mapRect(shape.bounds());
1351 drawBounds.intersect(fClip.conservativeBounds());
1352 if (pathAtlas->isSuitableForAtlasing(drawBounds)) {
1353 return {
nullptr, pathAtlas};
1374 return {renderers->tessellatedStrokes(),
nullptr};
1379 if (shape.convex() && !shape.inverted()) {
1382 return {renderers->convexTessellatedWedges(),
nullptr};
1384 Rect drawBounds = localToDevice.mapRect(shape.bounds());
1385 drawBounds.intersect(fClip.conservativeBounds());
1386 const bool preferWedges =
1390 drawBounds.isEmptyNegativeOrNaN() ||
1394 (shape.isPath() && shape.path().countVerbs() < 50) ||
1395 drawBounds.area() <= (256 * 256);
1398 return {renderers->stencilTessellatedWedges(shape.fillType()),
nullptr};
1400 return {renderers->stencilTessellatedCurvesAndTris(shape.fillType()),
nullptr};
1410void Device::flushPendingWorkToRecorder(
Recorder* recorder) {
1414 SkDEBUGCODE(intptr_t expected =
reinterpret_cast<intptr_t
>(recorder ? recorder : fRecorder);)
1415 SkASSERT(fPreRecorderSentinel == expected - 1);
1416 SkASSERT(fPostRecorderSentinel == expected + 1);
1418 SkASSERT(recorder ==
nullptr || recorder == fRecorder);
1419 if (recorder && recorder != fRecorder) {
1432 SkASSERT(!recorder || fScopedRecordingID == 0);
1433 SkASSERT(fScopedRecordingID == 0 || fScopedRecordingID == fRecorder->priv().nextRecordingID());
1454 this->internalFlush();
1455 sk_sp<Task> drawTask = fDC->snapDrawTask(fRecorder);
1456 if (this->isScratchDevice()) {
1459 fLastTask = drawTask;
1470 fLastTask =
nullptr;
1474 fRecorder->priv().add(std::move(drawTask));
1479 if (fDC->target()->mipmapped() == Mipmapped::kYes) {
1480 if (!
GenerateMipmaps(fRecorder, fDC->refTarget(), fDC->colorInfo())) {
1481 SKGPU_LOG_W(
"Device::flushPendingWorkToRecorder: Failed to generate mipmaps");
1486 fIsFlushing =
false;
1489void Device::internalFlush() {
1494 fRecorder->priv().atlasProvider()->recordUploads(fDC.get());
1498 fClip.recordDeferredClipDraws();
1501 fDC->flush(fRecorder);
1503 fColorDepthBoundsManager->reset();
1504 fDisjointStencilSet->reset();
1505 fCurrentDepth = DrawOrder::kClearDepth;
1508 fRecorder->priv().atlasProvider()->postFlush();
1511bool Device::needsFlushBeforeDraw(
int numNewRenderSteps, DstReadRequirement dstReadReq)
const {
1513 numNewRenderSteps += fClip.maxDeferredClipDraws() * Renderer::kMaxRenderSteps;
1515 (DrawList::kMaxRenderSteps - fDC->pendingRenderSteps()) < numNewRenderSteps ||
1517 dstReadReq == DstReadRequirement::kTextureCopy;
1528 if (!img || !
as_IB(img)->isGraphiteBacked()) {
1529 SKGPU_LOG_W(
"Couldn't get Graphite-backed special image as image");
1541 if (dst.isEmpty()) {
1549 DrawFlags::kIgnorePathEffect);
1558 {SkTo<uint16_t>(mask->
width()),
1559 SkTo<uint16_t>(mask->
height())}};
1561 auto maskProxyView = AsView(mask->
asImage());
1562 if (!maskProxyView) {
1563 SKGPU_LOG_W(
"Couldn't get Graphite-backed special image as texture proxy view");
1579 fRecorder->priv().textureDataCache()->insert(tdb);
1584 maskProxyView.proxy(),
1588 this->localToDeviceTransform().inverse(),
1595 DrawFlags::kIgnorePathEffect);
1611 if (forceCopy || !this->readSurfaceView() || this->readSurfaceView().proxy()->isFullyLazy()) {
1612 deviceImage = this->makeImageCopy(
1620 this->flushPendingWorkToRecorder();
1622 deviceImage = Image::WrapDevice(
sk_ref_sp(
this));
1623 finalSubset = subset;
1632 return SkSpecialImages::MakeGraphite(
1633 fRecorder, finalSubset, std::move(deviceImage), this->surfaceProps());
1638 return skif::MakeGraphiteBackend(fRecorder, surfaceProps,
colorType);
1645bool Device::isScratchDevice()
const {
1655 return !fDC->target()->isInstantiated() && !fDC->target()->isLazy();
1663 this->strikeDeviceInfo(),
1669 slugImpl->
subRuns()->draw(canvas, slugImpl->origin(),
paint, slugImpl, this->atlasDelegate());
1675 this->drawGeometry(this->localToDeviceTransform(),
1682 std::optional<AnalyticBlurMask> analyticBlur = AnalyticBlurMask::Make(
1683 this->recorder(), this->localToDeviceTransform(), deviceSigma, rrect);
1684 if (!analyticBlur) {
1688 this->drawGeometry(this->localToDeviceTransform(),
Geometry(*analyticBlur),
paint, style);
static int step(int x, SkScalar min, SkScalar max)
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
static const int points[]
#define SKGPU_LOG_E(fmt,...)
#define SKGPU_LOG_W(fmt,...)
static float next(float f)
@ kUnknown_SkAlphaType
uninitialized
#define SkAssertResult(cond)
@ kSrcOver
r = s + (1-sa)*d
SkBlenderBase * as_BB(SkBlender *blend)
@ kUnknown_SkColorType
uninitialized
constexpr SkColor SK_ColorWHITE
static SkColorType colorType(AImageDecoder *decoder, const AImageDecoderHeaderInfo *headerInfo)
static bool ok(int result)
SkRect SkModifyPaintAndDstForDrawImageRect(const SkImage *image, const SkSamplingOptions &, SkRect src, SkRect dst, bool strictSrcSubset, SkPaint *paint)
static SkImage_Base * as_IB(SkImage *image)
static std::unique_ptr< SkEncoder > Make(SkWStream *dst, const SkPixmap *src, const SkYUVAPixmaps *srcYUVA, const SkColorSpace *srcYUVAColorSpace, const SkJpegEncoder::Options &options)
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
sk_sp< T > sk_ref_sp(T *obj)
static constexpr bool SkToBool(const T &x)
#define TRACE_EVENT_SCOPE_NAME_THREAD
virtual std::optional< SkBlendMode > asBlendMode() const
static sk_sp< SkBlender > Mode(SkBlendMode mode)
virtual skgpu::graphite::Recorder * recorder() const
@ kStrict_SrcRectConstraint
sample only inside bounds; slower
@ kFast_SrcRectConstraint
sample outside bounds; faster
@ kLines_PointMode
draw each pair of points as a line segment
@ kPoints_PointMode
draw each point separately
bool isAlphaUnchanged() const
SkColorSpace * colorSpace() const
SkColorType colorType() const
void(ReadPixelsContext, std::unique_ptr< const AsyncReadResult >) ReadPixelsCallback
@ kButt_Cap
no stroke extension
void setColor(SkColor color)
@ kStroke_Style
set to stroke geometry
void setColor4f(const SkColor4f &color, SkColorSpace *colorSpace=nullptr)
void setShader(sk_sp< SkShader > shader)
void setBlendMode(SkBlendMode mode)
SkPath & setIsVolatile(bool isVolatile)
static SkPath Oval(const SkRect &, SkPathDirection=SkPathDirection::kCW)
void transform(const SkMatrix &matrix, SkPath *dst, SkApplyPerspectiveClip pc=SkApplyPerspectiveClip::kYes) const
static bool AllCornersCircular(const SkRRect &rr, SkScalar tolerance=SK_ScalarNearlyZero)
const SkRect & rect() const
static SkRRect MakeOval(const SkRect &oval)
bool getBoundaryPath(SkPath *path) const
const SkIRect & getBounds() const
bool op(const SkIRect &rect, Op op)
bool setRect(const SkIRect &rect)
bool setPath(const SkPath &path, const SkRegion &clip)
virtual bool isOpaque() const
virtual sk_sp< SkImage > asImage() const =0
const SkIRect & subset() const
static SkStrikeCache * GlobalStrikeCache()
SkScalar getWidth() const
SkPaint::Join getJoin() const
SkPaint::Cap getCap() const
void setResScale(SkScalar rs)
SkScalar getMiter() const
SkSurfaceProps cloneWithPixelGeometry(SkPixelGeometry newPixelGeometry) const
static std::tuple< bool, size_t > DrawAsTiledImageRect(SkCanvas *, const SkImage *, const SkRect &srcRect, const SkRect &dstRect, SkCanvas::QuadAAFlags, const SkSamplingOptions &, const SkPaint *, SkCanvas::SrcRectConstraint, size_t cacheSize, size_t maxTextureSize)
virtual TextureInfo getDefaultSampledTextureInfo(SkColorType, Mipmapped mipmapped, Protected, Renderable) const =0
DisjointStencilIndex add(CompressedPaintersOrder drawOrder, Rect rect)
IntersectionTreeSet()=default
static sk_sp< Device > Make(Recorder *recorder, sk_sp< TextureProxy >, SkISize deviceSize, const SkColorInfo &, const SkSurfaceProps &, LoadOp initialLoadOp, bool registerWithRecorder=true)
Recorder * recorder() const override
static sk_sp< DrawContext > Make(const Caps *caps, sk_sp< TextureProxy > target, SkISize deviceSize, const SkColorInfo &, const SkSurfaceProps &)
static constexpr DisjointStencilIndex kUnassigned
MonotonicValue next() const
static SkColor4f Color4fPrepForDst(SkColor4f srgb, const SkColorInfo &dstColorInfo)
Protected isProtected() const
const Caps * caps() const
ResourceProvider * resourceProvider()
void add(const SkSamplingOptions &sampling, const SkTileMode tileModes[2], sk_sp< TextureProxy > proxy)
static sk_sp< TextureProxy > Make(const Caps *, ResourceProvider *, SkISize dimensions, const TextureInfo &, skgpu::Budgeted)
virtual skgpu::MaskFormat maskFormat() const =0
virtual const VertexFiller & vertexFiller() const =0
virtual std::tuple< bool, int > regenerateAtlas(int begin, int end, RegenerateAtlasDelegate) const =0
virtual int glyphCount() const =0
const gpu::SubRunContainerOwner & subRuns() const
static sk_sp< SlugImpl > Make(const SkMatrix &viewMatrix, const sktext::GlyphRunList &glyphRunList, const SkPaint &paint, SkStrikeDeviceInfo strikeDeviceInfo, sktext::StrikeForGPUCacheInterface *strikeCache)
std::tuple< skgpu::graphite::Rect, skgpu::graphite::Transform > boundsAndDeviceMatrix(const skgpu::graphite::Transform &localToDevice, SkPoint drawOrigin) const
static const char * begin(const StringSlice &s)
FlutterSemanticsFlag flags
FlPixelBufferTexturePrivate * priv
#define ASSERT_SINGLE_OWNER
SkImage::ReadPixelsContext ReadPixelsContext
SkImage::ReadPixelsCallback ReadPixelsCallback
constexpr SkColor4f kTransparent
SK_API sk_sp< SkImage > RasterFromPixmap(const SkPixmap &pixmap, RasterReleaseProc rasterReleaseProc, ReleaseContext releaseContext)
SK_API sk_sp< SkImage > TextureFromImage(GrDirectContext *, const SkImage *, skgpu::Mipmapped=skgpu::Mipmapped::kNo, skgpu::Budgeted=skgpu::Budgeted::kYes)
Optional< SkRect > bounds
SK_API sk_sp< SkSurface > RenderTarget(GrRecordingContext *context, skgpu::Budgeted budgeted, const SkImageInfo &imageInfo, int sampleCount, GrSurfaceOrigin surfaceOrigin, const SkSurfaceProps *surfaceProps, bool shouldCreateWithMips=false, bool isProtected=false)
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 mode
bool GenerateMipmaps(Recorder *recorder, sk_sp< TextureProxy > texture, const SkColorInfo &colorInfo)
MonotonicValue< DisjointStencilIndexSequence > DisjointStencilIndex
DstReadRequirement GetDstReadRequirement(const Caps *caps, std::optional< SkBlendMode > blendMode, Coverage coverage)
static constexpr int kMaxBruteForceN
std::pair< sk_sp< SkImage >, SkSamplingOptions > GetGraphiteBacked(Recorder *recorder, const SkImage *imageIn, SkSamplingOptions sampling)
static constexpr int kMaxGridSize
MonotonicValue< CompressedPaintersOrderSequence > CompressedPaintersOrder
static constexpr int kGridCellSize
constexpr bool BlurIsEffectivelyIdentity(float sigma)
SkISize GetApproxSize(SkISize size)
std::function< void(const sktext::gpu::AtlasSubRun *subRun, SkPoint drawOrigin, const SkPaint &paint, sk_sp< SkRefCnt > subRunStorage, sktext::gpu::RendererData)> AtlasDrawDelegate
bool intersect(const SkIRect &r)
constexpr SkISize size() const
int32_t fTop
smaller y-axis bounds
static constexpr SkIRect MakeSize(const SkISize &size)
int32_t fLeft
smaller x-axis bounds
static constexpr SkIRect MakePtSize(SkIPoint pt, SkISize size)
const SkColorInfo & colorInfo() const
SkISize dimensions() const
SkColorType colorType() const
static SkRect Make(const SkISize &size)
static SkRect MakeIWH(int w, int h)
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
#define TRACE_EVENT0(category_group, name)
#define TRACE_EVENT_INSTANT0(category_group, name)