42enum class ClipGeometry {
51template<
typename A,
typename B>
52ClipGeometry get_clip_geometry(
const A&
a,
const B&
b) {
61 }
else if (
b.contains(
a)) {
63 return ClipGeometry::kAOnly;
64 }
else if (
a.contains(
b)) {
66 return ClipGeometry::kBOnly;
69 return ClipGeometry::kBoth;
76 return ClipGeometry::kAOnly;
77 }
else if (
b.contains(
a)) {
83 return ClipGeometry::kBoth;
93 return ClipGeometry::kBOnly;
94 }
else if (
a.contains(
b)) {
99 return ClipGeometry::kBoth;
107 return ClipGeometry::kAOnly;
108 }
else if (
b.contains(
a)) {
110 return ClipGeometry::kBOnly;
114 return ClipGeometry::kBoth;
131 if (!mixedAAMode && aToDevice == bToDevice) {
133 return a.conservativeContains(
b);
142 return a.conservativeContains(bInA);
159 for (
int i = 0;
i < 4; ++
i) {
162 if (!
a.conservativeContains(cornerInA)) {
190static uint32_t kInvalidGenID = 0;
191static uint32_t kEmptyGenID = 1;
192static uint32_t kWideOpenGenID = 2;
194uint32_t next_gen_id() {
196 static const uint32_t kFirstUnreservedGenID = 3;
197 static std::atomic<uint32_t> nextID{kFirstUnreservedGenID};
201 id = nextID.fetch_add(1, std::memory_order_relaxed);
202 }
while (
id < kFirstUnreservedGenID);
218 std::unique_ptr<GrFragmentProcessor>
fp) {
221 if (
e.fLocalToDevice.isIdentity()) {
222 if (
e.fShape.isRect()) {
224 }
else if (
e.fShape.isRRect()) {
233 e.fShape.asPath(&devicePath);
245 const GrOp* opBeingClipped,
249 std::unique_ptr<GrFragmentProcessor> inputFP) {
254 e.fShape.asPath(&
path);
258 path.toggleInverseFillType();
261 scissorBounds,
e.fLocalToDevice,
path);
305 inverted.setInverted(
true);
306 helper->
drawShape(inverted,
e.fLocalToDevice,
e.fAA, alpha);
308 helper->
drawShape(
e.fShape,
e.fLocalToDevice,
e.fAA, alpha);
320 taskGroup = direct->priv().getTaskGroup();
341 "ClipStack_RenderSwMask");
346 std::unique_ptr<Uploader> uploader = std::make_unique<Uploader>(
count);
348 uploader->data().push_back(*(elements[
i]));
351 Uploader* uploaderRaw = uploader.get();
352 auto drawAndUploadMask = [uploaderRaw,
bounds] {
353 TRACE_EVENT0(
"skia.gpu",
"Threaded SW Clip Mask Render");
356 for (
int i = 0;
i < uploaderRaw->data().
size(); ++
i) {
357 draw_to_sw_mask(&helper, uploaderRaw->data()[
i],
i == 0);
362 uploaderRaw->signalAndFreeData();
365 taskGroup->
add(std::move(drawAndUploadMask));
366 proxy->texPriv().setDeferredUploader(std::move(uploader));
376 draw_to_sw_mask(&helper,*(elements[
i]),
i == 0);
391 if (helper.
init(
bounds, genID,
out->windowRectsState().windows(), 0)) {
394 helper.
clear(startInside);
403 helper.
drawShape(
e.fShape,
e.fLocalToDevice, op,
e.fAA);
407 out->hardClip().addStencilClip(genID);
421 if (fOriginalBounds.
isEmpty()) {
422 fOriginalBounds = drawBounds;
431 bool contains(
const RawElement&
e)
const {
return false; }
432 bool contains(
const SaveRecord&
s)
const {
return false; }
450ClipStack::RawElement::RawElement(
const SkMatrix& localToDevice,
const GrShape& shape,
452 :
Element{shape, localToDevice, op, aa}
453 , fInnerBounds(
SkIRect::MakeEmpty())
454 , fOuterBounds(
SkIRect::MakeEmpty())
455 , fInvalidatedByIndex(-1) {
456 if (!localToDevice.
invert(&fDeviceToLocal)) {
463void ClipStack::RawElement::markInvalid(
const SaveRecord& current) {
465 fInvalidatedByIndex = current.firstActiveElementIndex();
468void ClipStack::RawElement::restoreValid(
const SaveRecord& current) {
469 if (current.firstActiveElementIndex() < fInvalidatedByIndex) {
470 fInvalidatedByIndex = -1;
475 if (fInnerBounds.contains(
d.outerBounds())) {
481 return shape_contains_rect(
fShape, fLocalToDevice, fDeviceToLocal,
487 if (fInnerBounds.contains(
s.outerBounds())) {
492 return shape_contains_rect(
fShape, fLocalToDevice, fDeviceToLocal,
500 if (fInnerBounds.contains(
e.fOuterBounds)) {
504 bool mixedAA = fAA !=
e.fAA;
505 if (!mixedAA && fLocalToDevice ==
e.fLocalToDevice) {
509 static constexpr int kMaxPathComparePoints = 16;
510 if (
fShape.isRRect() &&
e.fShape.isRRect()) {
513 }
else if (
fShape.isPath() &&
e.fShape.isPath()) {
514 return fShape.path().getGenerationID() ==
e.fShape.path().getGenerationID() ||
515 (
fShape.path().getPoints(
nullptr, 0) <= kMaxPathComparePoints &&
516 fShape.path() ==
e.fShape.path());
520 return shape_contains_rect(
fShape, fLocalToDevice, fDeviceToLocal,
521 e.fShape.bounds(),
e.fLocalToDevice, mixedAA);
530 fShape.setInverted(
false);
555 if (forceAA && !(
fShape.
isRect() && fLocalToDevice.preservesAxisAlignment())) {
563 if (fLocalToDevice.preservesAxisAlignment()) {
568 fLocalToDevice.setIdentity();
569 fDeviceToLocal.setIdentity();
575 fOuterBounds = outer.
round();
576 fInnerBounds = fOuterBounds;
579 SkASSERT(fOuterBounds.contains(fInnerBounds) || fInnerBounds.isEmpty());
581 }
else if (
fShape.isRRect()) {
585 if (
fShape.rrect().transform(fLocalToDevice, &
src)) {
587 fLocalToDevice.setIdentity();
588 fDeviceToLocal.setIdentity();
592 if (!fInnerBounds.intersect(deviceBounds)) {
599 if (fOuterBounds.isEmpty()) {
610bool ClipStack::RawElement::combine(
const RawElement& other,
const SaveRecord& current) {
620 bool shapeUpdated =
false;
622 bool aaMatch = fAA == other.fAA;
623 if (fLocalToDevice.isIdentity() && other.fLocalToDevice.isIdentity() && !aaMatch) {
638 if (aaMatch && fLocalToDevice == other.fLocalToDevice) {
639 if (!
fShape.rect().intersect(other.fShape.rect())) {
642 this->markInvalid(current);
648 (other.fShape.isRect() || other.fShape.isRRect())) {
650 if (fAA == other.fAA && fLocalToDevice == other.fLocalToDevice) {
666 }
else if (!
a.getBounds().intersects(
b.getBounds())) {
669 this->markInvalid(current);
680 if (!fInnerBounds.intersect(other.fInnerBounds)) {
689void ClipStack::RawElement::updateForElement(RawElement* added,
const SaveRecord& current) {
690 if (this->isInvalid()) {
696 switch (get_clip_geometry(*
this, *added)) {
699 this->markInvalid(current);
700 added->markInvalid(current);
703 case ClipGeometry::kAOnly:
705 added->markInvalid(current);
708 case ClipGeometry::kBOnly:
710 this->markInvalid(current);
713 case ClipGeometry::kBoth:
716 if (added->combine(*
this, current)) {
718 this->markInvalid(current);
754ClipStack::Mask::Mask(
const SaveRecord& current,
const SkIRect& drawBounds)
756 , fGenID(current.genID()) {
760 SkASSERT(fGenID != kInvalidGenID && fGenID != kEmptyGenID && fGenID != kWideOpenGenID);
773bool ClipStack::Mask::appliesToDraw(
const SaveRecord& current,
const SkIRect& drawBounds)
const {
776 SkASSERT(fGenID != current.genID() || ¤t == fOwner);
791ClipStack::SaveRecord::SaveRecord(
const SkIRect& deviceBounds)
792 : fInnerBounds(deviceBounds)
793 , fOuterBounds(deviceBounds)
795 , fStartingMaskIndex(0)
796 , fStartingElementIndex(0)
797 , fOldestValidIndex(0)
798 , fDeferredSaveCount(0)
801 , fGenID(kInvalidGenID) {}
803ClipStack::SaveRecord::SaveRecord(
const SaveRecord& prior,
804 int startingMaskIndex,
805 int startingElementIndex)
806 : fInnerBounds(prior.fInnerBounds)
807 , fOuterBounds(prior.fOuterBounds)
808 , fShader(prior.fShader)
809 , fStartingMaskIndex(startingMaskIndex)
810 , fStartingElementIndex(startingElementIndex)
811 , fOldestValidIndex(prior.fOldestValidIndex)
812 , fDeferredSaveCount(0)
813 , fStackOp(prior.fStackOp)
814 , fState(prior.fState)
815 , fGenID(kInvalidGenID) {
818 SkASSERT(startingMaskIndex >= prior.fStartingMaskIndex);
820 SkASSERT(startingElementIndex >= prior.fStartingElementIndex);
823uint32_t ClipStack::SaveRecord::genID()
const {
827 return kWideOpenGenID;
831 SkASSERT(fGenID != kEmptyGenID && fGenID != kWideOpenGenID);
845 return fInnerBounds.contains(
draw.outerBounds());
849 return fInnerBounds.contains(element.outerBounds());
852void ClipStack::SaveRecord::removeElements(RawElement::Stack* elements) {
853 while (elements->count() > fStartingElementIndex) {
854 elements->pop_back();
858void ClipStack::SaveRecord::restoreElements(RawElement::Stack* elements) {
863 int i = elements->count() - 1;
864 for (RawElement&
e : elements->ritems()) {
865 if (
i < fOldestValidIndex) {
868 e.restoreValid(*
this);
873void ClipStack::SaveRecord::invalidateMasks(
GrProxyProvider* proxyProvider,
874 Mask::Stack* masks) {
876 while (masks->count() > fStartingMaskIndex) {
877 SkASSERT(masks->back().owner() ==
this && proxyProvider);
878 masks->back().invalidate(proxyProvider);
881 SkASSERT(masks->empty() || masks->back().genID() != fGenID);
886 fOldestValidIndex = fStartingElementIndex;
898 fShader = std::move(shader);
907bool ClipStack::SaveRecord::addElement(RawElement&& toAdd, RawElement::Stack* elements) {
910 SkASSERT((toAdd.shape().isEmpty() || !toAdd.outerBounds().isEmpty()) &&
911 (toAdd.innerBounds().isEmpty() || toAdd.outerBounds().contains(toAdd.innerBounds())));
918 }
else if (toAdd.shape().isEmpty()) {
927 switch (get_clip_geometry(*
this, toAdd)) {
933 case ClipGeometry::kAOnly:
937 case ClipGeometry::kBOnly:
940 this->replaceWithElement(std::move(toAdd), elements);
943 case ClipGeometry::kBoth:
953 this->replaceWithElement(std::move(toAdd), elements);
963 if (!fInnerBounds.intersect(toAdd.innerBounds())) {
973 fOuterBounds =
subtract(fOuterBounds, toAdd.innerBounds(),
true);
974 fInnerBounds =
subtract(fInnerBounds, toAdd.outerBounds(),
false);
980 SkIRect oldOuter = fOuterBounds;
981 fOuterBounds =
subtract(toAdd.outerBounds(), fInnerBounds,
true);
982 fInnerBounds =
subtract(toAdd.innerBounds(), oldOuter,
false);
987 fOuterBounds.join(toAdd.outerBounds());
988 if (toAdd.innerBounds().width() * toAdd.innerBounds().height() >
989 fInnerBounds.width() * fInnerBounds.height()) {
990 fInnerBounds = toAdd.innerBounds();
999 (fInnerBounds.isEmpty() || fOuterBounds.contains(fInnerBounds)));
1001 return this->appendElement(std::move(toAdd), elements);
1004bool ClipStack::SaveRecord::appendElement(RawElement&& toAdd, RawElement::Stack* elements) {
1006 int i = elements->count() - 1;
1011 int youngestValid = fStartingElementIndex - 1;
1014 int oldestValid = elements->count();
1018 RawElement* oldestActiveInvalid =
nullptr;
1019 int oldestActiveInvalidIndex = elements->count();
1021 for (RawElement& existing : elements->ritems()) {
1022 if (
i < fOldestValidIndex) {
1027 existing.updateForElement(&toAdd, *
this);
1029 if (toAdd.isInvalid()) {
1030 if (existing.isInvalid()) {
1038 }
else if (existing.isInvalid()) {
1041 if (
i >= fStartingElementIndex) {
1043 oldestActiveInvalid = &existing;
1044 oldestActiveInvalidIndex =
i;
1049 if (
i > youngestValid) {
1058 SkASSERT(oldestValid == elements->count() ||
1059 (oldestValid >= fOldestValidIndex && oldestValid < elements->
count()));
1060 SkASSERT(youngestValid == fStartingElementIndex - 1 ||
1061 (youngestValid >= fStartingElementIndex && youngestValid < elements->
count()));
1062 SkASSERT((oldestActiveInvalid && oldestActiveInvalidIndex >= fStartingElementIndex &&
1063 oldestActiveInvalidIndex < elements->
count()) || !oldestActiveInvalid);
1066 SkASSERT(oldestValid >= fOldestValidIndex);
1067 fOldestValidIndex =
std::min(oldestValid, oldestActiveInvalidIndex);
1074 int targetCount = youngestValid + 1;
1075 if (!oldestActiveInvalid || oldestActiveInvalidIndex >= targetCount) {
1078 oldestActiveInvalid =
nullptr;
1080 while (elements->count() > targetCount) {
1081 SkASSERT(oldestActiveInvalid != &elements->back());
1082 elements->pop_back();
1084 if (oldestActiveInvalid) {
1085 *oldestActiveInvalid = std::move(toAdd);
1086 }
else if (elements->count() < targetCount) {
1087 elements->push_back(std::move(toAdd));
1089 elements->back() = std::move(toAdd);
1093 fGenID = next_gen_id();
1097void ClipStack::SaveRecord::replaceWithElement(RawElement&& toAdd, RawElement::Stack* elements) {
1099 fInnerBounds = toAdd.innerBounds();
1100 fOuterBounds = toAdd.outerBounds();
1101 fStackOp = toAdd.op();
1102 fState = toAdd.clipType();
1105 int targetCount = fStartingElementIndex + 1;
1106 while (elements->count() > targetCount) {
1107 elements->pop_back();
1109 if (elements->count() < targetCount) {
1110 elements->push_back(std::move(toAdd));
1112 elements->back() = std::move(toAdd);
1115 SkASSERT(elements->count() == fStartingElementIndex + 1);
1118 fOldestValidIndex = fStartingElementIndex;
1119 fGenID = next_gen_id();
1151 , fProxyProvider(nullptr)
1152 , fDeviceBounds(deviceBounds)
1154 , fForceAA(forceAA) {
1163 if (fProxyProvider) {
1164 for (Mask&
m : fMasks.
ritems()) {
1165 m.invalidate(fProxyProvider);
1172 fSaves.
back().pushSave();
1177 SaveRecord& current = fSaves.
back();
1178 if (current.popSave()) {
1185 current.removeElements(&fElements);
1187 if (fProxyProvider) {
1188 current.invalidateMasks(fProxyProvider, &fMasks);
1192 fSaves.
back().restoreElements(&fElements);
1196 const SaveRecord& current = this->currentSaveRecord();
1200 return fDeviceBounds;
1205 return subtract(fDeviceBounds, current.innerBounds(),
true);
1208 return current.outerBounds();
1215 if (!
draw.applyDeviceBounds(fDeviceBounds)) {
1219 const SaveRecord& cs = this->currentSaveRecord();
1229 switch (get_clip_geometry(cs,
draw)) {
1234 case ClipGeometry::kBOnly:
1238 case ClipGeometry::kAOnly:
1245 case ClipGeometry::kBoth: {
1247 const RawElement& back = fElements.
back();
1250 return {back.shape().rect(), back.aa()};
1253 return {back.shape().rrect(), back.aa()};
1274 if (!fProxyProvider) {
1283 if (!
draw.applyDeviceBounds(fDeviceBounds)) {
1288 const SaveRecord& cs = this->currentSaveRecord();
1298 std::unique_ptr<GrFragmentProcessor> clipFP =
nullptr;
1313 switch (get_clip_geometry(cs,
draw)) {
1317 case ClipGeometry::kBOnly:
1320 out->addCoverageFP(std::move(clipFP));
1326 case ClipGeometry::kAOnly:
1331 case ClipGeometry::kBoth:
1346 scissorBounds = cs.outerBounds();
1348 scissorBounds =
subtract(
draw.outerBounds(), cs.innerBounds(),
true);
1355 bool scissorIsNeeded =
SkToBool(cs.shader());
1368 bool maskRequiresAA =
false;
1371 int i = fElements.
count();
1372 for (
const RawElement&
e : fElements.
ritems()) {
1374 if (
i < cs.oldestElementIndex()) {
1377 }
else if (
e.isInvalid()) {
1381 switch (get_clip_geometry(
e,
draw)) {
1387 case ClipGeometry::kBOnly:
1391 case ClipGeometry::kAOnly:
1396 case ClipGeometry::kBoth: {
1398 scissorIsNeeded =
true;
1402 bool fullyApplied =
false;
1416 fullyApplied =
true;
1420 if (!fullyApplied) {
1424 fullyApplied =
e.innerBounds() ==
e.outerBounds() ||
1425 e.innerBounds().contains(scissorBounds);
1427 if (!
e.innerBounds().isEmpty() &&
1428 windowRects.
count() < maxWindowRectangles) {
1432 fullyApplied =
e.innerBounds() ==
e.outerBounds();
1437 if (!fullyApplied && remainingAnalyticFPs > 0) {
1438 std::tie(fullyApplied, clipFP) = analytic_clip_fp(
e.asElement(),
1441 if (!fullyApplied && atlasPathRenderer) {
1442 std::tie(fullyApplied, clipFP) = clip_atlas_fp(sdc, op,
1444 scissorBounds,
e.asElement(),
1448 remainingAnalyticFPs--;
1452 if (!fullyApplied) {
1462 if (!scissorIsNeeded) {
1473 out->hardClip().addScissor(scissorBounds,
bounds);
1475 if (!windowRects.
empty()) {
1481 if (!elementsForMask.
empty()) {
1482 bool stencilUnavailable =
1485 bool hasSWMask =
false;
1487 stencilUnavailable) {
1490 std::tie(hasSWMask, clipFP) = GetSWMaskFP(
1491 rContext, &fMasks, cs, scissorBounds, elementsForMask.
begin(),
1492 elementsForMask.
size(), std::move(clipFP));
1496 if (stencilUnavailable) {
1497 SkDebugf(
"WARNING: Clip mask requires stencil, but stencil unavailable. "
1498 "Draw will be ignored.\n");
1502 render_stencil_mask(rContext, sdc, cs.genID(), scissorBounds,
1510 out->addCoverageFP(std::move(clipFP));
1517ClipStack::SaveRecord& ClipStack::writableSaveRecord(
bool* wasDeferred) {
1518 SaveRecord& current = fSaves.
back();
1519 if (current.canBeUpdated()) {
1521 *wasDeferred =
false;
1526 *wasDeferred =
true;
1538 this->writableSaveRecord(&wasDeferred).addShader(std::move(shader));
1544 SaveRecord&
save = this->writableSaveRecord(&wasDeferred);
1547 save.removeElements(&fElements);
1548 save.invalidateMasks(fProxyProvider, &fMasks);
1551 save.reset(fDeviceBounds);
1552 if (
rect != fDeviceBounds) {
1557void ClipStack::clip(RawElement&& element) {
1566 element.simplify(fDeviceBounds, fForceAA);
1567 SkASSERT(!element.shape().inverted());
1571 if (element.shape().isEmpty()) {
1581 SaveRecord&
save = this->writableSaveRecord(&wasDeferred);
1584 if (!
save.addElement(
std::move(element), &fElements)) {
1588 SkASSERT(elementCount == fElements.count());
1590 fSaves.
back().pushSave();
1598 if (fProxyProvider && !wasDeferred) {
1600 save.invalidateMasks(fProxyProvider, &fMasks);
1608 std::unique_ptr<GrFragmentProcessor> clipFP) {
1614 for (
const Mask&
m : masks->ritems()) {
1615 if (
m.genID() != current.genID()) {
1618 if (
m.appliesToDraw(current,
bounds)) {
1622 maskBounds =
m.bounds();
1630 maskProxy = render_sw_mask(context,
bounds, elements,
count);
1637 Mask& mask = masks->emplace_back(current,
bounds);
1651 subset.offset(-maskBounds.
fLeft, -maskBounds.
fTop);
1654 auto domain = subset.makeInset(0.5, 0.5);
1656 samplerState, subset, domain, *context->
priv().
caps());
1660 fp = GrBlendFragmentProcessor::Make<SkBlendMode::kDstIn>(std::move(
fp), std::move(clipFP));
SkAssertResult(font.textToGlyphs("Hello", 5, SkTextEncoding::kUTF8, glyphs, std::size(glyphs))==count)
static GrFPResult GrFPSuccess(std::unique_ptr< GrFragmentProcessor > fp)
std::tuple< bool, std::unique_ptr< GrFragmentProcessor > > GrFPResult
static GrFPResult GrFPFailure(std::unique_ptr< GrFragmentProcessor > fp)
@ kTopLeft_GrSurfaceOrigin
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
#define SkDEBUGFAIL(message)
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
static bool subtract(const R &a, const R &b, R *out)
SkDEBUGCODE(SK_SPI) SkThreadID SkGetThreadID()
static constexpr bool SkToBool(const T &x)
static EdgeMap simplify(const EdgeMap &edges, SkPathFillType fillType)
static void draw(SkCanvas *canvas, SkRect &target, int x, int y)
const GrCaps * caps() const
const GrShaderCaps * shaderCaps() const
GrBackendFormat getDefaultBackendFormat(GrColorType, GrRenderable) const
skgpu::Swizzle getReadSwizzle(const GrBackendFormat &format, GrColorType colorType) const
static bool IsPixelAligned(const SkRect &rect)
static SkIRect GetPixelIBounds(const SkRect &bounds, GrAA aa, BoundsType mode=BoundsType::kExterior)
static constexpr SkScalar kBoundsTolerance
static bool IsInsideClip(const SkIRect &innerClipBounds, const SkRect &drawBounds, GrAA aa)
virtual GrDirectContext * asDirectContext()
static GrFPResult Make(std::unique_ptr< GrFragmentProcessor > inputFP, GrClipEdgeType edgeType, int n, const float edges[])
virtual ClipResult clipToShape(skgpu::ganesh::SurfaceDrawContext *, SkClipOp, const SkMatrix &, const GrShape &, GrAA)
skgpu::ganesh::AtlasPathRenderer * getAtlasPathRenderer()
static std::unique_ptr< GrFragmentProcessor > DeviceSpace(std::unique_ptr< GrFragmentProcessor >)
static std::unique_ptr< GrFragmentProcessor > Rect(std::unique_ptr< GrFragmentProcessor >, GrClipEdgeType, SkRect)
static std::unique_ptr< GrFragmentProcessor > MulInputByChildAlpha(std::unique_ptr< GrFragmentProcessor > child)
GrSurfaceProxyView findCachedProxyWithColorTypeFallback(const skgpu::UniqueKey &, GrSurfaceOrigin, GrColorType, int sampleCnt)
sk_sp< GrTextureProxy > createProxy(const GrBackendFormat &, SkISize dimensions, GrRenderable, int renderTargetSampleCnt, skgpu::Mipmapped, SkBackingFit, skgpu::Budgeted, GrProtected, std::string_view label, GrInternalSurfaceFlags=GrInternalSurfaceFlags::kNone, UseAllocator useAllocator=UseAllocator::kYes)
bool assignUniqueKeyToProxy(const skgpu::UniqueKey &, GrTextureProxy *)
void processInvalidUniqueKey(const skgpu::UniqueKey &, GrTextureProxy *, InvalidateGPUResource)
static GrQuad MakeFromRect(const SkRect &, const SkMatrix &)
SkPoint point(int i) const
skvx::Vec< 4, float > w4f() const
GrDrawingManager * drawingManager()
GrProxyProvider * proxyProvider()
GrRecordingContextPriv priv()
bool canUseStencil(const GrCaps &caps) const
void drawShape(const GrStyledShape &, const SkMatrix &matrix, GrAA, uint8_t alpha)
void clear(uint8_t alpha)
bool init(const SkIRect &resultBounds)
GrSurfaceProxyView toTextureView(GrRecordingContext *, SkBackingFit fit)
GrTextureProxy * asTextureProxy() const
GrSurfaceOrigin origin() const
static std::unique_ptr< GrFragmentProcessor > MakeSubset(GrSurfaceProxyView, SkAlphaType, const SkMatrix &, GrSamplerState, const SkRect &subset, const GrCaps &caps, const float border[4]=kDefaultBorder, bool alwaysUseShaderTileMode=false)
SkIRect & addWindow(const SkIRect &window)
static SkMatrix Translate(SkScalar dx, SkScalar dy)
void mapPoints(SkPoint dst[], const SkPoint src[], int count) const
bool invert(SkMatrix *inverse) const
static const SkMatrix & I()
bool preservesAxisAlignment() const
bool mapRect(SkRect *dst, const SkRect &src, SkApplyPerspectiveClip pc=SkApplyPerspectiveClip::kYes) const
static constexpr SkScalar kW0PlaneDistance
void transform(const SkMatrix &matrix, SkPath *dst, SkApplyPerspectiveClip pc=SkApplyPerspectiveClip::kYes) const
static SkRect InnerBounds(const SkRRect &rr)
static SkRRect ConservativeIntersect(const SkRRect &a, const SkRRect &b)
const SkRect & rect() const
static SkRRect MakeRect(const SkRect &r)
static bool Subtract(const SkRect &a, const SkRect &b, SkRect *out)
@ kReplace_Op
replace target with operand
@ kIntersect_Op
target intersected with operand
@ kDifference_Op
target minus operand
T & emplace_back(Args &&... args)
void add(std::function< void(void)> fn)
static Domain GenerateDomain()
GrFPResult makeAtlasClipEffect(const skgpu::ganesh::SurfaceDrawContext *, const GrOp *opBeingClipped, std::unique_ptr< GrFragmentProcessor > inputFP, const SkIRect &drawBounds, const SkMatrix &, const SkPath &)
const SkRect & bounds() const
const SkIRect & outerBounds() const
Draw(const SkRect &drawBounds, GrAA aa)
bool contains(const RawElement &e) const
bool applyDeviceBounds(const SkIRect &deviceBounds)
bool contains(const SaveRecord &s) const
GrClip::Effect apply(GrRecordingContext *, skgpu::ganesh::SurfaceDrawContext *, GrDrawOp *, GrAAType, GrAppliedClip *, SkRect *bounds) const override
GrClip::PreClipResult preApply(const SkRect &drawBounds, GrAA aa) const override
void clipShader(sk_sp< SkShader > shader)
ClipStack(const SkIRect &deviceBounds, const SkMatrix *ctm, bool forceAA)
void clipRect(const SkMatrix &ctm, const SkRect &rect, GrAA aa, SkClipOp op)
SkIRect getConservativeBounds() const override
void replaceClip(const SkIRect &rect)
GrRenderTargetProxy * asRenderTargetProxy()
bool canUseDynamicMSAA() const
int maxWindowRectangles() const
const SkSurfaceProps & surfaceProps() const
static void Draw(SkCanvas *canvas, const SkRect &rect)
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
uint32_t uint32_t * format
static float min(float r, float g, float b)
static constexpr auto kMaskOrigin
std::unique_ptr< GrFragmentProcessor > Make(const SkMaskFilter *maskfilter, const GrFPArgs &args, const SkMatrix &ctm)
void Outset(const skvx::float4 &edgeDistances, GrQuad *quad)
GrFPResult Make(std::unique_ptr< GrFragmentProcessor >, GrClipEdgeType, const SkRRect &, const GrShaderCaps &)
Optional< SkRect > bounds
sk_sp< SkBlender > blender SkRect rect
SK_API sk_sp< SkShader > Blend(SkBlendMode mode, sk_sp< SkShader > dst, sk_sp< SkShader > src)
DlVertices::Builder Builder
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
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
static constexpr int kNumStackMasks
static constexpr int kElementStackIncrement
static constexpr int kSaveStackIncrement
static constexpr int kMaskStackIncrement
static constexpr int kMaxAnalyticFPs
constexpr bool contains(std::string_view str, std::string_view needle)
SIT bool any(const Vec< 1, T > &x)
bool intersect(const SkIRect &r)
static bool Intersects(const SkIRect &a, const SkIRect &b)
int32_t fBottom
larger y-axis bounds
int32_t fTop
smaller y-axis bounds
static constexpr SkIRect MakeEmpty()
int32_t fLeft
smaller x-axis bounds
bool contains(int32_t x, int32_t y) const
int32_t fRight
larger x-axis bounds
static SkRect Make(const SkISize &size)
bool intersect(const SkRect &r)
void outset(float dx, float dy)
SkRect makeInset(float dx, float dy) const
bool contains(SkScalar x, SkScalar y) const
void round(SkIRect *dst) const
constexpr float height() const
constexpr float width() const
#define TRACE_EVENT0(category_group, name)