1272 {
1273
1274 if (!fProxyProvider) {
1275 fProxyProvider = rContext->priv().proxyProvider();
1276 }
1277 SkASSERT(fProxyProvider == rContext->priv().proxyProvider());
1278 const GrCaps* caps = rContext->priv().caps();
1279
1280
1281
1283 if (!
draw.applyDeviceBounds(fDeviceBounds)) {
1285 }
1287
1288 const SaveRecord& cs = this->currentSaveRecord();
1289
1295 }
1296
1297
1298 std::unique_ptr<GrFragmentProcessor> clipFP = nullptr;
1299 if (cs.shader()) {
1301 nullptr};
1305 if (clipFP) {
1306
1307
1309 }
1310 }
1311
1312
1313 switch (get_clip_geometry(cs,
draw)) {
1316
1317 case ClipGeometry::kBOnly:
1318
1319 if (clipFP) {
1320 out->addCoverageFP(std::move(clipFP));
1322 } else {
1324 }
1325
1326 case ClipGeometry::kAOnly:
1327
1329 [[fallthrough]];
1330
1331 case ClipGeometry::kBoth:
1332
1333
1337 break;
1338 }
1339
1340
1343
1344
1345
1346 scissorBounds = cs.outerBounds();
1347 } else {
1348 scissorBounds =
subtract(
draw.outerBounds(), cs.innerBounds(),
true);
1349 }
1350
1351
1352
1353
1354
1355 bool scissorIsNeeded =
SkToBool(cs.shader());
1357
1359
1360
1361 int maxWindowRectangles = sdc->maxWindowRectangles();
1363
1364
1365
1367
1368 bool maskRequiresAA = false;
1369 auto atlasPathRenderer = rContext->priv().drawingManager()->getAtlasPathRenderer();
1370
1371 int i = fElements.
count();
1372 for (
const RawElement&
e : fElements.
ritems()) {
1374 if (
i < cs.oldestElementIndex()) {
1375
1376 break;
1377 }
else if (
e.isInvalid()) {
1378 continue;
1379 }
1380
1381 switch (get_clip_geometry(
e,
draw)) {
1383
1384
1386
1387 case ClipGeometry::kBOnly:
1388
1389 break;
1390
1391 case ClipGeometry::kAOnly:
1392
1394 [[fallthrough]];
1395
1396 case ClipGeometry::kBoth: {
1397
1398 scissorIsNeeded = true;
1399
1400
1401
1402 bool fullyApplied = false;
1403
1404
1406 auto result = op->clipToShape(sdc,
e.op(),
e.localToDevice(),
e.shape(),
1411 }
1413
1415 }
1416 fullyApplied = true;
1418 }
1419
1420 if (!fullyApplied) {
1422
1423
1424 fullyApplied =
e.innerBounds() ==
e.outerBounds() ||
1425 e.innerBounds().contains(scissorBounds);
1426 } else {
1427 if (!
e.innerBounds().isEmpty() &&
1428 windowRects.
count() < maxWindowRectangles) {
1429
1430
1432 fullyApplied =
e.innerBounds() ==
e.outerBounds();
1433 }
1434 }
1435 }
1436
1437 if (!fullyApplied && remainingAnalyticFPs > 0) {
1438 std::tie(fullyApplied, clipFP) = analytic_clip_fp(
e.asElement(),
1440 std::move(clipFP));
1441 if (!fullyApplied && atlasPathRenderer) {
1442 std::tie(fullyApplied, clipFP) = clip_atlas_fp(sdc, op,
1443 atlasPathRenderer,
1444 scissorBounds,
e.asElement(),
1445 std::move(clipFP));
1446 }
1447 if (fullyApplied) {
1448 remainingAnalyticFPs--;
1449 }
1450 }
1451
1452 if (!fullyApplied) {
1455 }
1456
1457 break;
1458 }
1459 }
1460 }
1461
1462 if (!scissorIsNeeded) {
1463
1466 }
1467
1468
1471 }
1473 out->hardClip().addScissor(scissorBounds,
bounds);
1474 }
1475 if (!windowRects.
empty()) {
1477 }
1478
1479
1480
1481 if (!elementsForMask.
empty()) {
1482 bool stencilUnavailable =
1483 !sdc->asRenderTargetProxy()->canUseStencil(*rContext->priv().caps());
1484
1485 bool hasSWMask = false;
1486 if ((sdc->numSamples() <= 1 && !sdc->canUseDynamicMSAA() && maskRequiresAA) ||
1487 stencilUnavailable) {
1488
1489
1490 std::tie(hasSWMask, clipFP) = GetSWMaskFP(
1491 rContext, &fMasks, cs, scissorBounds, elementsForMask.
begin(),
1492 elementsForMask.
size(), std::move(clipFP));
1493 }
1494
1495 if (!hasSWMask) {
1496 if (stencilUnavailable) {
1497 SkDebugf(
"WARNING: Clip mask requires stencil, but stencil unavailable. "
1498 "Draw will be ignored.\n");
1500 } else {
1501
1502 render_stencil_mask(rContext, sdc, cs.genID(), scissorBounds,
1504 }
1505 }
1506 }
1507
1508 if (clipFP) {
1509
1510 out->addCoverageFP(std::move(clipFP));
1511 }
1512
1515}
SkAssertResult(font.textToGlyphs("Hello", 5, SkTextEncoding::kUTF8, glyphs, std::size(glyphs))==count)
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
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 void draw(SkCanvas *canvas, SkRect &target, int x, int y)
const GrShaderCaps * shaderCaps() const
static bool IsInsideClip(const SkIRect &innerClipBounds, const SkRect &drawBounds, GrAA aa)
static std::unique_ptr< GrFragmentProcessor > MulInputByChildAlpha(std::unique_ptr< GrFragmentProcessor > child)
SkIRect & addWindow(const SkIRect &window)
static void Draw(SkCanvas *canvas, const SkRect &rect)
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
std::unique_ptr< GrFragmentProcessor > Make(const SkMaskFilter *maskfilter, const GrFPArgs &args, const SkMatrix &ctm)
Optional< SkRect > bounds
static constexpr int kMaxAnalyticFPs
bool intersect(const SkIRect &r)
static SkRect Make(const SkISize &size)