/* * Copyright 2022 Google LLC * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "src/gpu/graphite/PaintParams.h" #include "include/core/SkColorSpace.h" #include "include/core/SkShader.h" #include "src/core/SkBlenderBase.h" #include "src/core/SkColorFilterBase.h" #include "src/core/SkColorSpacePriv.h" #include "src/gpu/graphite/KeyContext.h" #include "src/gpu/graphite/KeyHelpers.h" #include "src/gpu/graphite/PaintParamsKey.h" #include "src/gpu/graphite/PipelineData.h" #include "src/gpu/graphite/Uniform.h" #include "src/shaders/SkShaderBase.h" namespace skgpu::graphite { PaintParams::PaintParams(const SkColor4f& color, sk_sp finalBlender, sk_sp shader, sk_sp colorFilter, sk_sp primitiveBlender, bool skipColorXform) : fColor(color) , fFinalBlender(std::move(finalBlender)) , fShader(std::move(shader)) , fColorFilter(std::move(colorFilter)) , fPrimitiveBlender(std::move(primitiveBlender)) , fSkipColorXform(skipColorXform) {} PaintParams::PaintParams(const SkPaint& paint, sk_sp primitiveBlender, bool skipColorXform) : fColor(paint.getColor4f()) , fFinalBlender(paint.refBlender()) , fShader(paint.refShader()) , fColorFilter(paint.refColorFilter()) , fPrimitiveBlender(std::move(primitiveBlender)) , fSkipColorXform(skipColorXform) {} PaintParams::PaintParams(const PaintParams& other) = default; PaintParams::~PaintParams() = default; PaintParams& PaintParams::operator=(const PaintParams& other) = default; std::optional PaintParams::asFinalBlendMode() const { return fFinalBlender ? as_BB(fFinalBlender)->asBlendMode() : SkBlendMode::kSrcOver; } sk_sp PaintParams::refFinalBlender() const { return fFinalBlender; } sk_sp PaintParams::refShader() const { return fShader; } sk_sp PaintParams::refColorFilter() const { return fColorFilter; } sk_sp PaintParams::refPrimitiveBlender() const { return fPrimitiveBlender; } SkColor4f PaintParams::Color4fPrepForDst(SkColor4f srcColor, const SkColorInfo& dstColorInfo) { // xform from sRGB to the destination colorspace SkColorSpaceXformSteps steps(sk_srgb_singleton(), kUnpremul_SkAlphaType, dstColorInfo.colorSpace(), kUnpremul_SkAlphaType); SkColor4f result = srcColor; steps.apply(result.vec()); return result; } void PaintParams::toKey(const KeyContext& keyContext, PaintParamsKeyBuilder* builder, PipelineDataGatherer* gatherer) const { SkColor4f dstPaintColor = Color4fPrepForDst(fColor, keyContext.dstColorInfo()); // TODO: figure out how we can omit this block when the Paint's color isn't used. SolidColorShaderBlock::BeginBlock(keyContext, builder, gatherer, dstPaintColor.makeOpaque().premul()); builder->endBlock(); if (fShader) { as_SB(fShader)->addToKey(keyContext, builder, gatherer); } if (fPrimitiveBlender) { as_BB(fPrimitiveBlender)->addToKey(keyContext, builder, gatherer, /* primitiveColorBlender= */ true); } // Apply the paint's alpha value. auto alphaColorFilter = SkColorFilters::Blend({0, 0, 0, fColor.fA}, /* colorSpace= */ nullptr, SkBlendMode::kDstIn); if (alphaColorFilter) { as_CFB(alphaColorFilter)->addToKey(keyContext, builder, gatherer); } if (fColorFilter) { as_CFB(fColorFilter)->addToKey(keyContext, builder, gatherer); } if (fFinalBlender) { as_BB(fFinalBlender)->addToKey(keyContext, builder, gatherer, /* primitiveColorBlender= */ false); } else { BlendModeBlock::BeginBlock(keyContext, builder, gatherer, SkBlendMode::kSrcOver); builder->endBlock(); } SkASSERT(builder->sizeInBytes() > 0); } } // namespace skgpu::graphite