372 {
373 using ShaderMode = GrTextureEffect::ShaderMode;
374
376 auto* fb =
args.fFragBuilder;
377
378 if (te.fShaderModes[0] == ShaderMode::kNone &&
379 te.fShaderModes[1] == ShaderMode::kNone) {
380 fb->codeAppendf("return ");
381 fb->appendTextureLookup(fSamplerHandle,
args.fSampleCoord);
382 fb->codeAppendf(";");
383 } else {
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403 fb->codeAppendf(
"float2 inCoord = %s;",
args.fSampleCoord);
404
405 const auto&
m = te.fShaderModes;
406
407 const char* borderName = nullptr;
408 if (te.hasClampToBorderShaderMode()) {
409 fBorderUni =
args.fUniformHandler->addUniform(
411 }
412 auto modeUsesSubset = [](ShaderMode
m) {
414 case ShaderMode::kNone: return false;
415 case ShaderMode::kClamp: return false;
416 case ShaderMode::kRepeat_Nearest_None: return true;
417 case ShaderMode::kRepeat_Linear_None: return true;
418 case ShaderMode::kRepeat_Nearest_Mipmap: return true;
419 case ShaderMode::kRepeat_Linear_Mipmap: return true;
420 case ShaderMode::kMirrorRepeat: return true;
421 case ShaderMode::kClampToBorder_Nearest: return true;
422 case ShaderMode::kClampToBorder_Filter: return true;
423 }
425 };
426
427 auto modeUsesClamp = [](ShaderMode
m) {
429 case ShaderMode::kNone: return false;
430 case ShaderMode::kClamp: return true;
431 case ShaderMode::kRepeat_Nearest_None: return true;
432 case ShaderMode::kRepeat_Linear_None: return true;
433 case ShaderMode::kRepeat_Nearest_Mipmap: return true;
434 case ShaderMode::kRepeat_Linear_Mipmap: return true;
435 case ShaderMode::kMirrorRepeat: return true;
436 case ShaderMode::kClampToBorder_Nearest: return false;
437 case ShaderMode::kClampToBorder_Filter: return true;
438 }
440 };
441
442 bool useSubset[2] = {modeUsesSubset(
m[0]), modeUsesSubset(
m[1])};
443 bool useClamp [2] = {modeUsesClamp (
m[0]), modeUsesClamp (
m[1])};
444
445 const char* subsetName = nullptr;
446 if (useSubset[0] || useSubset[1]) {
447 fSubsetUni =
args.fUniformHandler->addUniform(
449 }
450
451 const char* clampName = nullptr;
452 if (useClamp[0] || useClamp[1]) {
453 fClampUni =
args.fUniformHandler->addUniform(
455 }
456
457 bool unormCoordsRequiredForShaderMode = ShaderModeRequiresUnormCoord(
m[0]) ||
458 ShaderModeRequiresUnormCoord(
m[1]);
459
460
461 SkASSERT(!(unormCoordsRequiredForShaderMode && te.matrixEffectShouldNormalize()));
462 bool sampleCoordsMustBeNormalized =
464
465 const char* idims = nullptr;
466 if (unormCoordsRequiredForShaderMode && sampleCoordsMustBeNormalized) {
467
468
471 }
472
473
474 auto read = [&](
const char* coord) {
477 if (idims) {
478 normCoord.
printf(
"(%s) * %s", coord, idims);
479 } else {
480 normCoord = coord;
481 }
482 fb->appendTextureLookup(&
result, fSamplerHandle, normCoord.
c_str());
484 };
485
486
487 auto subsetCoord = [&](ShaderMode
mode,
488 const char* coordSwizzle,
489 const char* subsetStartSwizzle,
490 const char* subsetStopSwizzle,
491 const char* extraCoord,
492 const char* coordWeight) {
494
495
496 case ShaderMode::kNone:
497 case ShaderMode::kClampToBorder_Nearest:
498 case ShaderMode::kClampToBorder_Filter:
499 case ShaderMode::kClamp:
500 fb->codeAppendf("subsetCoord.%s = inCoord.%s;", coordSwizzle, coordSwizzle);
501 break;
502 case ShaderMode::kRepeat_Nearest_None:
503 case ShaderMode::kRepeat_Linear_None:
504 fb->codeAppendf(
505 "subsetCoord.%s = mod(inCoord.%s - %s.%s, %s.%s - %s.%s) + %s.%s;",
506 coordSwizzle, coordSwizzle, subsetName, subsetStartSwizzle, subsetName,
507 subsetStopSwizzle, subsetName, subsetStartSwizzle, subsetName,
508 subsetStartSwizzle);
509 break;
510 case ShaderMode::kRepeat_Nearest_Mipmap:
511 case ShaderMode::kRepeat_Linear_Mipmap:
512
513
514
515
516
517
518
519
520
523 fb->codeAppend("{");
524 fb->codeAppendf("float w = %s.%s - %s.%s;", subsetName, subsetStopSwizzle,
525 subsetName, subsetStartSwizzle);
526 fb->codeAppendf("float w2 = 2 * w;");
527 fb->codeAppendf("float d = inCoord.%s - %s.%s;", coordSwizzle, subsetName,
528 subsetStartSwizzle);
529 fb->codeAppend("float m = mod(d, w2);");
530 fb->codeAppend("float o = mix(m, w2 - m, step(w, m));");
531 fb->codeAppendf("subsetCoord.%s = o + %s.%s;", coordSwizzle, subsetName,
532 subsetStartSwizzle);
533 fb->codeAppendf("%s = w - o + %s.%s;", extraCoord, subsetName,
534 subsetStartSwizzle);
535
536
537 fb->codeAppend("float hw = w/2;");
538 fb->codeAppend("float n = mod(d - hw, w2);");
539 fb->codeAppendf("%s = saturate(half(mix(n, w2 - n, step(w, n)) - hw + 0.5));",
540 coordWeight);
541 fb->codeAppend("}");
542 break;
543 case ShaderMode::kMirrorRepeat:
544 fb->codeAppend("{");
545 fb->codeAppendf("float w = %s.%s - %s.%s;", subsetName, subsetStopSwizzle,
546 subsetName, subsetStartSwizzle);
547 fb->codeAppendf("float w2 = 2 * w;");
548 fb->codeAppendf("float m = mod(inCoord.%s - %s.%s, w2);", coordSwizzle,
549 subsetName, subsetStartSwizzle);
550 fb->codeAppendf("subsetCoord.%s = mix(m, w2 - m, step(w, m)) + %s.%s;",
551 coordSwizzle, subsetName, subsetStartSwizzle);
552 fb->codeAppend("}");
553 break;
554 }
555 };
556
557 auto clampCoord = [&](
bool clamp,
558 const char* coordSwizzle,
559 const char* clampStartSwizzle,
560 const char* clampStopSwizzle) {
562 fb->codeAppendf("clampedCoord%s = clamp(subsetCoord%s, %s%s, %s%s);",
563 coordSwizzle, coordSwizzle,
564 clampName, clampStartSwizzle,
565 clampName, clampStopSwizzle);
566 } else {
567 fb->codeAppendf("clampedCoord%s = subsetCoord%s;", coordSwizzle, coordSwizzle);
568 }
569 };
570
571
572 const char* extraRepeatCoordX = nullptr;
573 const char* repeatCoordWeightX = nullptr;
574 const char* extraRepeatCoordY = nullptr;
575 const char* repeatCoordWeightY = nullptr;
576
577 bool mipmapRepeatX =
m[0] == ShaderMode::kRepeat_Nearest_Mipmap ||
578 m[0] == ShaderMode::kRepeat_Linear_Mipmap;
579 bool mipmapRepeatY =
m[1] == ShaderMode::kRepeat_Nearest_Mipmap ||
580 m[1] == ShaderMode::kRepeat_Linear_Mipmap;
581
582 if (mipmapRepeatX || mipmapRepeatY) {
583 fb->codeAppend("float2 extraRepeatCoord;");
584 }
585 if (mipmapRepeatX) {
586 fb->codeAppend("half repeatCoordWeightX;");
587 extraRepeatCoordX = "extraRepeatCoord.x";
588 repeatCoordWeightX = "repeatCoordWeightX";
589 }
590 if (mipmapRepeatY) {
591 fb->codeAppend("half repeatCoordWeightY;");
592 extraRepeatCoordY = "extraRepeatCoord.y";
593 repeatCoordWeightY = "repeatCoordWeightY";
594 }
595
596
597 fb->codeAppend("float2 subsetCoord;");
598 subsetCoord(te.fShaderModes[0], "x", "x", "z", extraRepeatCoordX, repeatCoordWeightX);
599 subsetCoord(te.fShaderModes[1], "y", "y", "w", extraRepeatCoordY, repeatCoordWeightY);
600 fb->codeAppend("float2 clampedCoord;");
601 if (useClamp[0] == useClamp[1]) {
602 clampCoord(useClamp[0], "", ".xy", ".zw");
603 } else {
604 clampCoord(useClamp[0], ".x", ".x", ".z");
605 clampCoord(useClamp[1], ".y", ".y", ".w");
606 }
607
608 if (mipmapRepeatX && mipmapRepeatY) {
609 fb->codeAppendf("extraRepeatCoord = clamp(extraRepeatCoord, %s.xy, %s.zw);",
610 clampName, clampName);
611 } else if (mipmapRepeatX) {
612 fb->codeAppendf("extraRepeatCoord.x = clamp(extraRepeatCoord.x, %s.x, %s.z);",
613 clampName, clampName);
614 } else if (mipmapRepeatY) {
615 fb->codeAppendf("extraRepeatCoord.y = clamp(extraRepeatCoord.y, %s.y, %s.w);",
616 clampName, clampName);
617 }
618
619
620
621
622 if (mipmapRepeatX && mipmapRepeatY) {
623 fb->codeAppendf(
624 "half4 textureColor ="
625 " mix(mix(%s, %s, repeatCoordWeightX),"
626 " mix(%s, %s, repeatCoordWeightX),"
627 " repeatCoordWeightY);",
628 read(
"clampedCoord").c_str(),
629 read(
"float2(extraRepeatCoord.x, clampedCoord.y)").c_str(),
630 read(
"float2(clampedCoord.x, extraRepeatCoord.y)").c_str(),
631 read(
"float2(extraRepeatCoord.x, extraRepeatCoord.y)").c_str());
632
633 } else if (mipmapRepeatX) {
634 fb->codeAppendf("half4 textureColor = mix(%s, %s, repeatCoordWeightX);",
635 read(
"clampedCoord").c_str(),
636 read(
"float2(extraRepeatCoord.x, clampedCoord.y)").c_str());
637 } else if (mipmapRepeatY) {
638 fb->codeAppendf("half4 textureColor = mix(%s, %s, repeatCoordWeightY);",
639 read(
"clampedCoord").c_str(),
640 read(
"float2(clampedCoord.x, extraRepeatCoord.y)").c_str());
641 } else {
642 fb->codeAppendf(
"half4 textureColor = %s;",
read(
"clampedCoord").c_str());
643 }
644
645
648
649
650
651 bool repeatLinearFilterX =
m[0] == ShaderMode::kRepeat_Linear_None ||
652 m[0] == ShaderMode::kRepeat_Linear_Mipmap;
653 bool repeatLinearFilterY =
m[1] == ShaderMode::kRepeat_Linear_None ||
654 m[1] == ShaderMode::kRepeat_Linear_Mipmap;
655 if (repeatLinearFilterX ||
m[0] == ShaderMode::kClampToBorder_Filter) {
656 fb->codeAppend("half errX = half(subsetCoord.x - clampedCoord.x);");
657 if (repeatLinearFilterX) {
658 fb->codeAppendf("float repeatCoordX = errX > 0 ? %s.x : %s.z;",
659 clampName, clampName);
660 repeatLinearReadX =
read(
"float2(repeatCoordX, clampedCoord.y)");
661 }
662 }
663 if (repeatLinearFilterY ||
m[1] == ShaderMode::kClampToBorder_Filter) {
664 fb->codeAppend("half errY = half(subsetCoord.y - clampedCoord.y);");
665 if (repeatLinearFilterY) {
666 fb->codeAppendf("float repeatCoordY = errY > 0 ? %s.y : %s.w;",
667 clampName, clampName);
668 repeatLinearReadY =
read(
"float2(clampedCoord.x, repeatCoordY)");
669 }
670 }
671
672
673
674
675
676 const char* ifStr = "if";
677 if (repeatLinearFilterX && repeatLinearFilterY) {
678 auto repeatLinearReadXY =
read(
"float2(repeatCoordX, repeatCoordY)");
679 fb->codeAppendf(
680 "if (errX != 0 && errY != 0) {"
681 " errX = abs(errX);"
682 " textureColor = mix(mix(textureColor, %s, errX),"
683 " mix(%s, %s, errX),"
684 " abs(errY));"
685 "}",
686 repeatLinearReadX.
c_str(), repeatLinearReadY.
c_str(),
687 repeatLinearReadXY.c_str());
688 ifStr = "else if";
689 }
690 if (repeatLinearFilterX) {
691 fb->codeAppendf(
692 "%s (errX != 0) {"
693 " textureColor = mix(textureColor, %s, abs(errX));"
694 "}",
695 ifStr, repeatLinearReadX.
c_str());
696 }
697 if (repeatLinearFilterY) {
698 fb->codeAppendf(
699 "%s (errY != 0) {"
700 " textureColor = mix(textureColor, %s, abs(errY));"
701 "}",
702 ifStr, repeatLinearReadY.
c_str());
703 }
704
705
706
707 if (
m[0] == ShaderMode::kClampToBorder_Filter) {
708 fb->codeAppendf("textureColor = mix(textureColor, %s, min(abs(errX), 1));", borderName);
709 }
710 if (
m[1] == ShaderMode::kClampToBorder_Filter) {
711 fb->codeAppendf("textureColor = mix(textureColor, %s, min(abs(errY), 1));", borderName);
712 }
713
714
715
716
717 if (
m[0] == ShaderMode::kClampToBorder_Nearest) {
718 fb->codeAppendf(
719 "float snappedX = floor(inCoord.x + 0.001) + 0.5;"
720 "if (snappedX < %s.x || snappedX > %s.z) {"
721 " textureColor = %s;"
722 "}",
723 subsetName, subsetName, borderName);
724 }
725 if (
m[1] == ShaderMode::kClampToBorder_Nearest) {
726 fb->codeAppendf(
727 "float snappedY = floor(inCoord.y + 0.001) + 0.5;"
728 "if (snappedY < %s.y || snappedY > %s.w) {"
729 " textureColor = %s;"
730 "}",
731 subsetName, subsetName, borderName);
732 }
733 fb->codeAppendf("return textureColor;");
734 }
735}
static unsigned clamp(SkFixed fx, int max)
static bool read(SkStream *stream, void *buffer, size_t amount)
void printf(const char format[],...) SK_PRINTF_LIKE(2
const char * c_str() const
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
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