Flutter Engine
The Flutter Engine
Functions
GrGradientShader Namespace Reference

Functions

static GrFPResult apply_matrix (std::unique_ptr< GrFragmentProcessor > fp, const SkShaders::MatrixRec &rec, const SkMatrix &postInv)
 
std::unique_ptr< GrFragmentProcessorMakeGradientFP (const SkGradientBaseShader &shader, const GrFPArgs &args, const SkShaders::MatrixRec &mRec, std::unique_ptr< GrFragmentProcessor > layout, const SkMatrix *overrideMatrix)
 
std::unique_ptr< GrFragmentProcessorMakeLinear (const SkLinearGradient &shader, const GrFPArgs &args, const SkShaders::MatrixRec &mRec)
 

Function Documentation

◆ apply_matrix()

static GrFPResult GrGradientShader::apply_matrix ( std::unique_ptr< GrFragmentProcessor fp,
const SkShaders::MatrixRec rec,
const SkMatrix postInv 
)
static

Produces an FP that muls its input coords by the inverse of the pending matrix and then samples the passed FP with those coordinates. 'postInv' is an additional matrix to post-apply to the inverted pending matrix. If the pending matrix is not invertible the GrFPResult's bool will be false and the passed FP will be returned to the caller in the GrFPResult.

Definition at line 781 of file GrGradientShader.cpp.

783 {
784 auto [total, ok] = rec.applyForFragmentProcessor(postInv);
785 if (!ok) {
786 return {false, std::move(fp)};
787 }
788 // GrMatrixEffect returns 'fp' if total worked out to identity.
789 return {true, GrMatrixEffect::Make(total, std::move(fp))};
790}
static bool ok(int result)
static std::unique_ptr< GrFragmentProcessor > Make(const SkMatrix &matrix, std::unique_ptr< GrFragmentProcessor > child)
std::tuple< SkMatrix, bool > applyForFragmentProcessor(const SkMatrix &postInv) const
const uint32_t fp

◆ MakeGradientFP()

std::unique_ptr< GrFragmentProcessor > GrGradientShader::MakeGradientFP ( const SkGradientBaseShader shader,
const GrFPArgs args,
const SkShaders::MatrixRec mRec,
std::unique_ptr< GrFragmentProcessor layout,
const SkMatrix overrideMatrix 
)

Definition at line 794 of file GrGradientShader.cpp.

798 {
799 // No shader is possible if a layout couldn't be created, e.g. a layout-specific Make() returned
800 // null.
801 if (layout == nullptr) {
802 return nullptr;
803 }
804
805 // Some two-point conical gradients use a custom matrix here. Otherwise, use
806 // SkGradientBaseShader's matrix;
807 if (!overrideMatrix) {
808 overrideMatrix = &shader.getGradientMatrix();
809 }
810 bool success;
811 std::tie(success, layout) = apply_matrix(std::move(layout), mRec, *overrideMatrix);
812 if (!success) {
813 return nullptr;
814 }
815
816 // Convert all colors into destination space and into SkPMColor4fs, and handle
817 // premul issues depending on the interpolation mode.
818 //
819 // SkGradientShader stores positions implicitly when they are evenly spaced, but the getPos()
820 // implementation performs a branch for every position index. Since the shader conversion
821 // requires lots of position tests, instruct the xformer to calculate all of the positions up
822 // front if needed.
823 SkColor4fXformer xformedColors(
824 &shader, args.fDstColorInfo->colorSpace(), /*forceExplicitPositions=*/true);
825 const SkPMColor4f* colors = xformedColors.fColors.begin();
826 const SkScalar* positions = xformedColors.fPositions;
827 const int colorCount = xformedColors.fColors.size();
828
829 bool allOpaque = true;
830 for (int i = 0; i < colorCount; i++) {
831 if (allOpaque && !SkScalarNearlyEqual(colors[i].fA, 1.0)) {
832 allOpaque = false;
833 }
834 }
835
836 // All gradients are colorized the same way, regardless of layout
837 std::unique_ptr<GrFragmentProcessor> colorizer = make_uniform_colorizer(
838 colors, positions, colorCount, shader.interpolateInPremul(), args);
839
840 if (colorizer) {
841 // If we made a uniform colorizer, wrap it in a conversion from interpolated space to
842 // destination. This also applies any final premultiplication.
843 colorizer = make_interpolated_to_dst(std::move(colorizer),
844 shader.fInterpolation,
845 xformedColors.fIntermediateColorSpace.get(),
846 *args.fDstColorInfo,
847 allOpaque);
848 } else {
849 // If we failed to make a uniform colorizer, we need to rasterize the gradient to a
850 // texture (which can handle arbitrarily complex gradients). This method directly encodes
851 // the result of the interpolated-to-dst into the texture, so we skip the wrapper FP above.
852 //
853 // Also, note that the texture technique has limited sampling resolution, and always blurs
854 // hard-stops.)
856 positions,
857 colorCount,
858 allOpaque,
859 shader.fInterpolation,
860 xformedColors.fIntermediateColorSpace.get(),
861 args.fDstColorInfo->colorSpace(),
862 args);
863 }
864
865 if (colorizer == nullptr) {
866 return nullptr;
867 }
868
869 // If interpolation space is different than destination, wrap the colorizer in a conversion.
870 // This also handles any final premultiplication, etc.
871
872 // All tile modes are supported (unless something was added to SkShader)
873 std::unique_ptr<GrFragmentProcessor> gradient;
874 switch(shader.getTileMode()) {
876 gradient = make_tiled_gradient(args, std::move(colorizer), std::move(layout),
877 /* mirror */ false, allOpaque);
878 break;
880 gradient = make_tiled_gradient(args, std::move(colorizer), std::move(layout),
881 /* mirror */ true, allOpaque);
882 break;
883 case SkTileMode::kClamp: {
884 // For the clamped mode, the border colors are the first and last colors, corresponding
885 // to t=0 and t=1, because SkGradientBaseShader enforces that by adding color stops as
886 // appropriate. If there is a hard stop, this grabs the expected outer colors for the
887 // border.
888
889 // However, we need to finish converting to destination color space. (These are still
890 // in the interpolated color space).
891 SkPMColor4f borderColors[2] = { colors[0], colors[colorCount - 1] };
892 SkArenaAlloc alloc(/*firstHeapAllocation=*/0);
893 SkRasterPipeline p(&alloc);
894 SkRasterPipeline_MemoryCtx ctx = { borderColors, 0 };
895
896 p.append(SkRasterPipelineOp::load_f32, &ctx);
898 &p,
899 &alloc,
900 allOpaque,
901 shader.fInterpolation,
902 xformedColors.fIntermediateColorSpace.get(),
903 args.fDstColorInfo->colorSpace());
904 p.append(SkRasterPipelineOp::store_f32, &ctx);
905 p.run(0, 0, 2, 1);
906
907 gradient = make_clamped_gradient(std::move(colorizer), std::move(layout),
908 borderColors[0], borderColors[1], allOpaque);
909 break;
910 }
912 // Even if the gradient colors are opaque, the decal borders are transparent so
913 // disable that optimization
914 gradient = make_clamped_gradient(std::move(colorizer), std::move(layout),
916 /* colorsAreOpaque */ false);
917 break;
918 }
919
920 return gradient;
921}
static std::unique_ptr< GrFragmentProcessor > make_clamped_gradient(std::unique_ptr< GrFragmentProcessor > colorizer, std::unique_ptr< GrFragmentProcessor > gradLayout, SkPMColor4f leftBorderColor, SkPMColor4f rightBorderColor, bool colorsAreOpaque)
static std::unique_ptr< GrFragmentProcessor > make_uniform_colorizer(const SkPMColor4f *colors, const SkScalar *positions, int count, bool premul, const GrFPArgs &args)
static std::unique_ptr< GrFragmentProcessor > make_tiled_gradient(const GrFPArgs &args, std::unique_ptr< GrFragmentProcessor > colorizer, std::unique_ptr< GrFragmentProcessor > gradLayout, bool mirror, bool colorsAreOpaque)
static std::unique_ptr< GrFragmentProcessor > make_interpolated_to_dst(std::unique_ptr< GrFragmentProcessor > gradient, const SkGradientShader::Interpolation &interpolation, SkColorSpace *intermediateColorSpace, const GrColorInfo &dstInfo, bool allOpaque)
static std::unique_ptr< GrFragmentProcessor > make_textured_colorizer(const SkPMColor4f *colors, const SkScalar *positions, int count, bool colorsAreOpaque, const SkGradientShader::Interpolation &interpolation, const SkColorSpace *intermediateColorSpace, const SkColorSpace *dstColorSpace, const GrFPArgs &args)
constexpr SkPMColor4f SK_PMColor4fTRANSPARENT
Definition: SkColorData.h:378
static bool SkScalarNearlyEqual(SkScalar x, SkScalar y, SkScalar tolerance=SK_ScalarNearlyZero)
Definition: SkScalar.h:107
bool interpolateInPremul() const
static void AppendInterpolatedToDstStages(SkRasterPipeline *p, SkArenaAlloc *alloc, bool colorsAreOpaque, const Interpolation &interpolation, const SkColorSpace *intermediateColorSpace, const SkColorSpace *dstColorSpace)
const SkMatrix & getGradientMatrix() const
SkTileMode getTileMode() const
float SkScalar
Definition: extension.cpp:12
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
static GrFPResult apply_matrix(std::unique_ptr< GrFragmentProcessor > fp, const SkShaders::MatrixRec &rec, const SkMatrix &postInv)
PODArray< SkColor > colors
Definition: SkRecords.h:276

◆ MakeLinear()

std::unique_ptr< GrFragmentProcessor > GrGradientShader::MakeLinear ( const SkLinearGradient shader,
const GrFPArgs args,
const SkShaders::MatrixRec mRec 
)

Definition at line 923 of file GrGradientShader.cpp.

925 {
926 // We add a tiny delta to t. When gradient stops are set up so that a hard stop in a vertically
927 // or horizontally oriented gradient falls exactly at a column or row of pixel centers we can
928 // get slightly different interpolated t values along the column/row. By adding the delta
929 // we will consistently get the color to the "right" of the stop. Of course if the hard stop
930 // falls at X.5 - delta then we still could get inconsistent results, but that is much less
931 // likely. crbug.com/938592
932 // If/when we add filtering of the gradient this can be removed.
934 "half4 main(float2 coord) {"
935 "return half4(half(coord.x) + 0.00001, 1, 0, 0);" // y = 1 for always valid
936 "}"
937 );
938 // The linear gradient never rejects a pixel so it doesn't change opacity
939 auto fp = GrSkSLFP::Make(effect, "LinearLayout", /*inputFP=*/nullptr,
941 return MakeGradientFP(shader, args, mRec, std::move(fp));
942}
SkRuntimeEffect * SkMakeRuntimeEffect(SkRuntimeEffect::Result(*make)(SkString, const SkRuntimeEffect::Options &), const char *sksl, SkRuntimeEffect::Options options=SkRuntimeEffect::Options{})
static std::unique_ptr< GrSkSLFP > Make(const SkRuntimeEffect *effect, const char *name, std::unique_ptr< GrFragmentProcessor > inputFP, OptFlags optFlags, Args &&... args)
Definition: GrSkSLFP.h:159
static Result MakeForShader(SkString sksl, const Options &)
std::unique_ptr< GrFragmentProcessor > MakeGradientFP(const SkGradientBaseShader &shader, const GrFPArgs &args, const SkShaders::MatrixRec &mRec, std::unique_ptr< GrFragmentProcessor > layout, const SkMatrix *overrideMatrix)