Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2f12edd6 authored by Robert Phillips's avatar Robert Phillips Committed by Android (Google) Code Review
Browse files

Merge "Add PaintOptionsBuilder" into main

parents b9325d59 2901a278
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -98,6 +98,7 @@ filegroup {
        "skia/compat/GraphiteBackendTexture.cpp",
        "skia/compat/GraphiteGpuContext.cpp",
        "skia/compat/GraphitePipelineManager.cpp",
        "skia/compat/PaintOptionsBuilder.cpp",
        "skia/debug/CaptureTimer.cpp",
        "skia/debug/CommonPool.cpp",
        "skia/debug/SkiaCapture.cpp",
+73 −273
Original line number Diff line number Diff line
@@ -31,12 +31,13 @@

#include <type_traits>

#include "PaintOptionsBuilder.h"
#include "skia/filters/RuntimeEffectManager.h"

namespace android::renderengine::skia {

using namespace skgpu::graphite;

using namespace PaintOptionsUtils;
using PrecompileShaders::ImageShaderFlags;

using ::skgpu::graphite::DrawTypeFlags;
@@ -151,239 +152,6 @@ skgpu::graphite::PaintOptions LinearEffect(sk_sp<SkRuntimeEffect> linearEffect,
// NOTE: keep in sync with upstream external/skia/tests/graphite/precompile/PrecompileTestUtils.cpp
// clang-format off

PaintOptions SolidSrcover() {
    PaintOptions paintOptions;
    paintOptions.setBlendModes({ SkBlendMode::kSrcOver });
    return paintOptions;
}

PaintOptions SolidMatrixCFSrcover() {
    PaintOptions paintOptions;

    paintOptions.setColorFilters({ PrecompileColorFilters::Matrix() });
    paintOptions.setBlendModes({ SkBlendMode::kSrcOver });

    return paintOptions;
}

PaintOptions TransparentPaintImagePremulHWOnlyMatrixCFSrcover() {
    PaintOptions paintOptions;

    SkColorInfo ci { kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr };
    paintOptions.setShaders({ PrecompileShaders::Image(ImageShaderFlags::kExcludeCubic,
                                                       { &ci, 1 },
                                                       {}) });
    paintOptions.setColorFilters({ PrecompileColorFilters::Matrix() });
    paintOptions.setBlendModes({ SkBlendMode::kSrcOver });
    paintOptions.setPaintColorIsOpaque(false);
    return paintOptions;
}

PaintOptions TransparentPaintImagePremulHWOnlyMatrixCFDitherSrcover() {
    PaintOptions paintOptions;

    SkColorInfo ci { kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr };
    paintOptions.setShaders({ PrecompileShaders::Image(ImageShaderFlags::kExcludeCubic,
                                                       { &ci, 1 },
                                                       {}) });
    paintOptions.setColorFilters({ PrecompileColorFilters::Matrix() });
    paintOptions.setBlendModes({ SkBlendMode::kSrcOver });
    paintOptions.setPaintColorIsOpaque(false);
    paintOptions.setDither(true);
    return paintOptions;
}

PaintOptions TransparentPaintImageSRGBHWOnlyMatrixCFDitherSrcover() {
    SkColorInfo ci { kRGBA_8888_SkColorType,
                     kPremul_SkAlphaType,
                     SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kAdobeRGB) };

    PaintOptions paintOptions;

    paintOptions.setShaders({ PrecompileShaders::Image(ImageShaderFlags::kExcludeCubic,
                                                       { &ci, 1 },
                                                       {}) });
    paintOptions.setColorFilters({ PrecompileColorFilters::Matrix() });
    paintOptions.setBlendModes({ SkBlendMode::kSrcOver });
    paintOptions.setPaintColorIsOpaque(false);
    paintOptions.setDither(true);
    return paintOptions;
}

PaintOptions TransparentPaintImagePremulHWOnlySrcover() {
    PaintOptions paintOptions;

    SkColorInfo ci { kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr };
    paintOptions.setShaders({ PrecompileShaders::Image(ImageShaderFlags::kExcludeCubic,
                                                       { &ci, 1 },
                                                       {}) });
    paintOptions.setBlendModes({ SkBlendMode::kSrcOver });
    paintOptions.setPaintColorIsOpaque(false);
    return paintOptions;
}

PaintOptions TransparentPaintImageSRGBHWOnlySrcover() {
    SkColorInfo ci { kRGBA_8888_SkColorType,
                     kPremul_SkAlphaType,
                     SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kAdobeRGB) };

    PaintOptions paintOptions;

    paintOptions.setShaders({ PrecompileShaders::Image(ImageShaderFlags::kExcludeCubic,
                                                       { &ci, 1 },
                                                       {}) });
    paintOptions.setBlendModes({ SkBlendMode::kSrcOver });
    paintOptions.setPaintColorIsOpaque(false);
    return paintOptions;
}

PaintOptions SolidSrcSrcover() {
    PaintOptions paintOptions;
    paintOptions.setBlendModes({ SkBlendMode::kSrc, SkBlendMode::kSrcOver });
    return paintOptions;
}

PaintOptions ImagePremulHWOnlySrc() {
    PaintOptions paintOptions;

    SkColorInfo ci { kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr };
    paintOptions.setShaders({ PrecompileShaders::Image(ImageShaderFlags::kExcludeCubic,
                                                       { &ci, 1 },
                                                       {}) });
    paintOptions.setBlendModes({ SkBlendMode::kSrc });
    return paintOptions;
}

PaintOptions ImagePremulHWOnlySrcover() {
    PaintOptions paintOptions;

    SkColorInfo ci { kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr };
    paintOptions.setShaders({ PrecompileShaders::Image(ImageShaderFlags::kExcludeCubic,
                                                       { &ci, 1 },
                                                       {}) });
    paintOptions.setBlendModes({ SkBlendMode::kSrcOver });
    return paintOptions;
}

PaintOptions ImageAlphaPremulHWOnlyMatrixCFSrcover() {
    PaintOptions paintOptions;

    SkColorInfo ci { kAlpha_8_SkColorType, kUnpremul_SkAlphaType, nullptr };
    paintOptions.setShaders({ PrecompileShaders::Image(ImageShaderFlags::kExcludeCubic,
                                                       { &ci, 1 },
                                                       {}) });
    paintOptions.setColorFilters({ PrecompileColorFilters::Matrix() });

    paintOptions.setBlendModes({ SkBlendMode::kSrcOver });
    return paintOptions;
}

PaintOptions ImageAlphaSRGBHWOnlyMatrixCFSrcover() {
    // Note: this is different from the other SRGB ColorInfos
    SkColorInfo ci { kAlpha_8_SkColorType,
                     kUnpremul_SkAlphaType,
                     SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kAdobeRGB) };

    PaintOptions paintOptions;

    paintOptions.setShaders({ PrecompileShaders::Image(ImageShaderFlags::kExcludeCubic,
                                                       { &ci, 1 },
                                                       {}) });
    paintOptions.setColorFilters({ PrecompileColorFilters::Matrix() });

    paintOptions.setBlendModes({ SkBlendMode::kSrcOver });
    return paintOptions;
}

PaintOptions ImageAlphaClampNoCubicSrc() {
    SkColorInfo ci { kAlpha_8_SkColorType, kUnpremul_SkAlphaType, nullptr };
    SkTileMode tm = SkTileMode::kClamp;

    PaintOptions paintOptions;
    paintOptions.setShaders({ PrecompileShaders::Image(ImageShaderFlags::kExcludeCubic,
                                                       { &ci, 1 },
                                                       { &tm, 1 }) });
    paintOptions.setBlendModes({ SkBlendMode::kSrc });
    return paintOptions;
}

PaintOptions ImagePremulHWOnlyMatrixCFSrcover() {
    PaintOptions paintOptions;

    SkColorInfo ci { kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr };
    paintOptions.setShaders({ PrecompileShaders::Image(ImageShaderFlags::kExcludeCubic,
                                                       { &ci, 1 },
                                                       {}) });
    paintOptions.setColorFilters({ PrecompileColorFilters::Matrix() });

    paintOptions.setBlendModes({ SkBlendMode::kSrcOver });
    return paintOptions;
}

PaintOptions ImageSRGBHWOnlyMatrixCFSrcover() {
    PaintOptions paintOptions;

    SkColorInfo ci { kRGBA_8888_SkColorType,
                     kPremul_SkAlphaType,
                     SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kAdobeRGB) };

    paintOptions.setShaders({ PrecompileShaders::Image(ImageShaderFlags::kExcludeCubic,
                                                       { &ci, 1 },
                                                       {}) });
    paintOptions.setColorFilters({ PrecompileColorFilters::Matrix() });

    paintOptions.setBlendModes({ SkBlendMode::kSrcOver });
    return paintOptions;
}

PaintOptions ImagePremulHWOnlyMatrixCFDitherSrcover() {
    PaintOptions paintOptions;

    SkColorInfo ci { kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr };
    paintOptions.setShaders({ PrecompileShaders::Image(ImageShaderFlags::kExcludeCubic,
                                                       { &ci, 1 },
                                                       {}) });
    paintOptions.setColorFilters({ PrecompileColorFilters::Matrix() });

    paintOptions.setBlendModes({ SkBlendMode::kSrcOver });
    paintOptions.setDither(true);

    return paintOptions;
}

PaintOptions ImageSRGBHWOnlyMatrixCFDitherSrcover() {
    SkColorInfo ci { kRGBA_8888_SkColorType,
                     kPremul_SkAlphaType,
                     SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kAdobeRGB) };

    PaintOptions paintOptions;

    paintOptions.setShaders({ PrecompileShaders::Image(ImageShaderFlags::kExcludeCubic,
                                                       { &ci, 1 },
                                                       {}) });
    paintOptions.setColorFilters({ PrecompileColorFilters::Matrix() });

    paintOptions.setBlendModes({ SkBlendMode::kSrcOver });
    paintOptions.setDither(true);

    return paintOptions;
}

PaintOptions ImageHWOnlySRGBSrcover() {
    PaintOptions paintOptions;

    SkColorInfo ci { kRGBA_8888_SkColorType,
                     kPremul_SkAlphaType,
                     SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB,
                                           SkNamedGamut::kAdobeRGB) };
    paintOptions.setShaders({ PrecompileShaders::Image(ImageShaderFlags::kExcludeCubic,
                                                       { &ci, 1 },
                                                       {}) });

    paintOptions.setBlendModes({ SkBlendMode::kSrcOver });
    return paintOptions;
}

// TODO(b/426601394): Update this to take an SkColorInfo for the input image.
// The other MouriMap* precompile paint options should use a linear SkColorInfo
// derived from this same input image.
@@ -805,75 +573,105 @@ void GraphitePipelineManager::PrecompilePipelines(
    // external/skia/tests/graphite/precompile/AndroidPrecompileTest.cpp
    // clang-format off
    const PrecompileSettings precompileCases[] = {
/*  0 */ { ImagePremulHWOnlySrcover(),         DrawTypeFlags::kNonAAFillRect,   kRGBA16F_1_D },
/*  1 */ { ImagePremulHWOnlySrcover(),
         { Builder().hwImg(kPremul).srcOver(),
           DrawTypeFlags::kNonAAFillRect,
           kRGBA16F_1_D },

         { Builder().hwImg(kPremul).srcOver(),
           kRRectAndNonAARect,
           kRGBA_1_D,
           kWithAnalyticClip },

/*  2 */ { ImagePremulHWOnlySrcover(),         kRRectAndNonAARect,              kRGBA_4_DS },
         { Builder().hwImg(kPremul).srcOver(),
           kRRectAndNonAARect,
           kRGBA_4_DS },

         { Builder().hwImg(kSRGB).srcOver(),
           DrawTypeFlags::kNonAAFillRect,
           kRGBA16F_1_D_SRGB },

/*  3 */ { ImageHWOnlySRGBSrcover(),           DrawTypeFlags::kNonAAFillRect,   kRGBA16F_1_D_SRGB },
/*  4 */ { ImageHWOnlySRGBSrcover(),
         { Builder().hwImg(kSRGB).srcOver(),
           kRRectAndNonAARect,
           kRGBA_1_D_SRGB,
           kWithAnalyticClip },

/*  5 */ { TransparentPaintImagePremulHWOnlySrcover(),
         { Builder().transparent().hwImg(kPremul).srcOver(),
           kRRectAndNonAARect,
           kRGBA_1_D,
           kWithAnalyticClip },
/*  6 */ { TransparentPaintImagePremulHWOnlySrcover(), kRRectAndNonAARect,      kRGBA_4_DS },

/*  7 */ { TransparentPaintImageSRGBHWOnlySrcover(), kRRectAndNonAARect,        kRGBA_1_D_SRGB },
         { Builder().transparent().hwImg(kPremul).srcOver(),
           kRRectAndNonAARect,
           kRGBA_4_DS },

         { Builder().transparent().hwImg(kSRGB).srcOver(),
           kRRectAndNonAARect,
           kRGBA_1_D_SRGB },

/*  8 */ { SolidSrcSrcover(),
         { Builder().src().srcOver(),
           kRRectAndNonAARect,
           kRGBA_1_D,
           kWithAnalyticClip },

/*  9 */ { SolidSrcover(),                     kRRectAndNonAARect,              kRGBA_4_DS },
         { Builder().srcOver(),
           kRRectAndNonAARect,
           kRGBA_4_DS },

/* 10 */ { ImagePremulHWOnlyMatrixCFSrcover(),
         { Builder().hwImg(kPremul).matrixCF().srcOver(),
           kRRectAndNonAARect,
           kRGBA_1_D,
           kWithAnalyticClip },

/* 11 */ { TransparentPaintImagePremulHWOnlyMatrixCFSrcover(),
         { Builder().transparent().hwImg(kPremul).matrixCF().srcOver(),
           kRRectAndNonAARect,
           kRGBA_1_D,
           kWithAnalyticClip },

/* 12 */ { TransparentPaintImagePremulHWOnlyMatrixCFDitherSrcover(),
                                               kRRectAndNonAARect,              kRGBA_1_D },
/* 13 */ { TransparentPaintImagePremulHWOnlyMatrixCFDitherSrcover(),
                                               DrawTypeFlags::kNonAAFillRect,   kRGBA_4_DS },
         { Builder().transparent().hwImg(kPremul).matrixCF().dither().srcOver(),
           kRRectAndNonAARect,
           kRGBA_1_D },

         { Builder().transparent().hwImg(kPremul).matrixCF().dither().srcOver(),
           DrawTypeFlags::kNonAAFillRect,
           kRGBA_4_DS },

/* 14 */ { ImagePremulHWOnlyMatrixCFDitherSrcover(),
         { Builder().hwImg(kPremul).matrixCF().dither().srcOver(),
           kRRectAndNonAARect,
           kRGBA_1_D,
           kWithAnalyticClip },

/* 15 */ { ImagePremulHWOnlyMatrixCFDitherSrcover(), DrawTypeFlags::kNonAAFillRect, kRGBA_4_DS },
         { Builder().hwImg(kPremul).matrixCF().dither().srcOver(),
           DrawTypeFlags::kNonAAFillRect,
           kRGBA_4_DS },

/* 16 */ { TransparentPaintImageSRGBHWOnlyMatrixCFDitherSrcover(),
         { Builder().transparent().hwImg(kSRGB).matrixCF().dither().srcOver(),
           kRRectAndNonAARect,
           kRGBA_1_D_SRGB },

/* 17 */ { ImageSRGBHWOnlyMatrixCFDitherSrcover(),
         { Builder().hwImg(kSRGB).matrixCF().dither().srcOver(),
           kRRectAndNonAARect,
           kRGBA_1_D_SRGB,
           kWithAnalyticClip },

/* 18 */ { ImageSRGBHWOnlyMatrixCFDitherSrcover(), DrawTypeFlags::kAnalyticRRect, kRGBA_4_DS_SRGB },
         { Builder().hwImg(kSRGB).matrixCF().dither().srcOver(),
           DrawTypeFlags::kAnalyticRRect,
           kRGBA_4_DS_SRGB },

/* 19 */ { ImageAlphaSRGBHWOnlyMatrixCFSrcover(),
         { Builder().hwImg(kAlphaSRGB).matrixCF().srcOver(),
           DrawTypeFlags::kNonAAFillRect,
           kRGBA_1D_4DS_SRGB },

/* 20 */ { ImagePremulHWOnlySrc(),             kRRectAndNonAARect,              kRGBA_1_D },
/* 21 */ { ImagePremulHWOnlySrc(),             DrawTypeFlags::kPerEdgeAAQuad,   kRGBA_1_D },
/* 22 */ { ImagePremulHWOnlySrc(),             DrawTypeFlags::kNonAAFillRect,   kRGBA_4_DS },
         { Builder().hwImg(kPremul).src(),
           kRRectAndNonAARect,
           kRGBA_1_D },

         { Builder().hwImg(kPremul).src(),
           DrawTypeFlags::kPerEdgeAAQuad,
           kRGBA_1_D },

         { Builder().hwImg(kPremul).src(),
           DrawTypeFlags::kNonAAFillRect,
           kRGBA_4_DS },

// TODO(b/426601394): Group these paint option settings into a function that accepts an input
// image color space so that the intermediate linear color spaces adapt correctly.
@@ -944,18 +742,20 @@ void GraphitePipelineManager::PrecompilePipelines(
           DrawTypeFlags::kAnalyticRRect,
           kRGBA_1_D_SRGB },

/* 38 */ { SolidSrcover(), DrawTypeFlags::kNonSimpleShape, kRGBA_4_DS },
         { Builder().srcOver(),
           DrawTypeFlags::kNonSimpleShape,
           kRGBA_4_DS },

// AnalyticClip block - all the PrecompileOptions here are just clones of earlier ones
// with an additional kAnalyticClip flag

// Note: this didn't get folded into #2 since the RRect draw isn't appearing w/ a clip
/* 39 */ { ImagePremulHWOnlySrcover(),
         { Builder().hwImg(kPremul).srcOver(),
           DrawTypeFlags::kNonAAFillRect | DrawTypeFlags::kAnalyticClip,
           kRGBA_4_DS },

// Note: this didn't get folded into #9 since the RRect draw isn't appearing w/ a clip
/* 40 */ { SolidSrcSrcover(),
         { Builder().src().srcOver(),
           DrawTypeFlags::kNonAAFillRect | DrawTypeFlags::kAnalyticClip,
           kRGBA_4_DS },

@@ -986,11 +786,11 @@ void GraphitePipelineManager::PrecompilePipelines(
           kRGBA_1_D,
           kWithAnalyticClip },

/* 47 */ { ImageAlphaClampNoCubicSrc(),
         { Builder().hwImg(kAlpha, kClamp).src(),
           DrawTypeFlags::kNonAAFillRect,
           kR_1_D },

/* 48 */ { ImageSRGBHWOnlyMatrixCFSrcover(),
         { Builder().hwImg(kSRGB).matrixCF().srcOver(),
           kRRectAndNonAARect,
           kRGBA_1_D_SRGB },

+139 −0
Original line number Diff line number Diff line
/*
 * Copyright 2025 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// NOTE: keep in sync with upstream external/skia/tests/graphite/precompile/PaintOptionsBuilder.cpp

#include "PaintOptionsBuilder.h"

#include <include/gpu/graphite/precompile/PrecompileColorFilter.h>
#include <include/gpu/graphite/precompile/PrecompileShader.h>

namespace android::renderengine::skia {

namespace PaintOptionsUtils {

using namespace skgpu::graphite;
using PrecompileShaders::GradientShaderFlags;
using PrecompileShaders::ImageShaderFlags;
using PrecompileShaders::YUVImageShaderFlags;

Builder& Builder::hwImg(ImgColorInfo ci, ImgTileModeOptions tmOptions) {
    static const SkColorInfo kAlphaInfo(kAlpha_8_SkColorType, kUnpremul_SkAlphaType, nullptr);
    static const SkColorInfo kAlphaSRGBInfo(kAlpha_8_SkColorType, kUnpremul_SkAlphaType,
                                            SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB,
                                                                  SkNamedGamut::kAdobeRGB));
    static const SkColorInfo kPremulInfo(kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr);
    static const SkColorInfo kSRGBInfo(kRGBA_8888_SkColorType, kPremul_SkAlphaType,
                                       SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB,
                                                             SkNamedGamut::kAdobeRGB));

    SkSpan<const SkColorInfo> ciSpan;
    switch (ci) {
        case kAlpha:
            ciSpan = {&kAlphaInfo, 1};
            break;
        case kAlphaSRGB:
            ciSpan = {&kAlphaSRGBInfo, 1};
            break;
        case kPremul:
            ciSpan = {&kPremulInfo, 1};
            break;
        case kSRGB:
            ciSpan = {&kSRGBInfo, 1};
            break;
    }

    static const SkTileMode kClampTM = SkTileMode::kClamp;
    static const SkTileMode kRepeatTM = SkTileMode::kRepeat;

    SkSpan<const SkTileMode> tmSpan;
    switch (tmOptions) {
        case kNone:
            break;
        case kClamp:
            tmSpan = {&kClampTM, 1};
            break;
        case kRepeat:
            tmSpan = {&kRepeatTM, 1};
            break;
    }

    sk_sp<PrecompileShader> img =
            PrecompileShaders::Image(ImageShaderFlags::kExcludeCubic, ciSpan, tmSpan);
    fPaintOptions.setShaders({std::move(img)});
    return *this;
}

Builder& Builder::yuv(YUVSamplingOptions options) {
    static const SkColorInfo kSRGBInfo(kRGBA_8888_SkColorType, kPremul_SkAlphaType,
                                       SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB,
                                                             SkNamedGamut::kAdobeRGB));

    YUVImageShaderFlags flags = YUVImageShaderFlags::kNone;
    switch (options) {
        case kNoCubic:
            flags = YUVImageShaderFlags::kExcludeCubic;
            break;
        case kHWAndShader:
            flags = YUVImageShaderFlags::kNoCubicNoNonSwizzledHW;
            break;
    }

    sk_sp<PrecompileShader> img = PrecompileShaders::YUVImage(flags, {&kSRGBInfo, 1});
    fPaintOptions.setShaders({std::move(img)});
    return *this;
}

Builder& Builder::linearGrad(LinearGradientOptions options) {
    sk_sp<PrecompileShader> gradient;

    if (options == kSmall) {
        gradient = PrecompileShaders::LinearGradient(GradientShaderFlags::kSmall);
    } else if (options == kComplex) {
        gradient = PrecompileShaders::
                LinearGradient(GradientShaderFlags::kNoLarge,
                               {SkGradientShader::Interpolation::InPremul::kNo,
                                SkGradientShader::Interpolation::ColorSpace::kSRGB,
                                SkGradientShader::Interpolation::HueMethod::kShorter});
    }

    fPaintOptions.setShaders({std::move(gradient)});
    return *this;
}

Builder& Builder::blend() {
    SkColorInfo ci{kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr};
    sk_sp<PrecompileShader> img =
            PrecompileShaders::Image(ImageShaderFlags::kExcludeCubic, {&ci, 1}, {});
    SkBlendMode kBlendModes = SkBlendMode::kPlus;
    fPaintOptions.setShaders({PrecompileShaders::Blend({&kBlendModes, 1}, {std::move(img)},
                                                       {PrecompileShaders::Color()})});
    return *this;
}

Builder& Builder::matrixCF() {
    fPaintOptions.setColorFilters({PrecompileColorFilters::Matrix()});
    return *this;
}

Builder& Builder::porterDuffCF() {
    fPaintOptions.setColorFilters({PrecompileColorFilters::Blend({SkBlendMode::kSrcOver})});
    return *this;
}

} // namespace PaintOptionsUtils

} // namespace android::renderengine::skia
+98 −0
Original line number Diff line number Diff line
/*
 * Copyright 2025 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// NOTE: keep in sync with upstream external/skia/tests/graphite/precompile/PaintOptionsBuilder.h

#ifndef PaintOptionsBuilder_DEFINED
#define PaintOptionsBuilder_DEFINED

#include <include/gpu/graphite/precompile/PaintOptions.h>

namespace android::renderengine::skia {

namespace PaintOptionsUtils {

enum ImgColorInfo {
    kAlpha,
    kAlphaSRGB,
    kPremul,
    kSRGB,
};

enum ImgTileModeOptions {
    kNone,
    kClamp,
    kRepeat,
};

// This enum directly maps to YUVImageShaderFlags but, crucially, is more compact.
enum YUVSamplingOptions {
    kNoCubic,     // YUVImageShaderFlags::kExcludeCubic
    kHWAndShader, // YUVImageShaderFlags::kNoCubicNoNonSwizzledHW
};

enum LinearGradientOptions {
    kSmall,
    kComplex, // idiosyncratic case - c.f. Builder::linearGrad
};

// This is a minimal builder object that allows for compact construction of the most common
// PaintOptions combinations - eliminating a lot of boilerplate.
class Builder {
public:
    Builder() {}

    // Shaders
    Builder& hwImg(ImgColorInfo ci, ImgTileModeOptions tmOptions = kNone);
    Builder& yuv(YUVSamplingOptions options);
    Builder& linearGrad(LinearGradientOptions options);
    Builder& blend();

    // ColorFilters
    Builder& matrixCF();
    Builder& porterDuffCF();

    // Blendmodes
    Builder& clear() { return this->addBlendMode(SkBlendMode::kClear); }
    Builder& dstIn() { return this->addBlendMode(SkBlendMode::kDstIn); }
    Builder& src() { return this->addBlendMode(SkBlendMode::kSrc); }
    Builder& srcOver() { return this->addBlendMode(SkBlendMode::kSrcOver); }

    // Misc settings
    Builder& transparent() {
        fPaintOptions.setPaintColorIsOpaque(false);
        return *this;
    }
    Builder& dither() {
        fPaintOptions.setDither(true);
        return *this;
    }

    operator skgpu::graphite::PaintOptions() const { return fPaintOptions; }

private:
    skgpu::graphite::PaintOptions fPaintOptions;

    Builder& addBlendMode(SkBlendMode bm) {
        fPaintOptions.addBlendMode(bm);
        return *this;
    }
};

} // namespace PaintOptionsUtils

} // namespace android::renderengine::skia
#endif // PaintOptionsBuilder_DEFINED