summaryrefslogtreecommitdiffstats
path: root/gfx/skia/skia/src/shaders/SkColorShader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/skia/skia/src/shaders/SkColorShader.cpp')
-rw-r--r--gfx/skia/skia/src/shaders/SkColorShader.cpp275
1 files changed, 275 insertions, 0 deletions
diff --git a/gfx/skia/skia/src/shaders/SkColorShader.cpp b/gfx/skia/skia/src/shaders/SkColorShader.cpp
new file mode 100644
index 0000000000..149b155d62
--- /dev/null
+++ b/gfx/skia/skia/src/shaders/SkColorShader.cpp
@@ -0,0 +1,275 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "include/core/SkColorSpace.h"
+#include "include/core/SkFlattenable.h"
+#include "src/base/SkArenaAlloc.h"
+#include "src/base/SkUtils.h"
+#include "src/core/SkColorSpacePriv.h"
+#include "src/core/SkColorSpaceXformSteps.h"
+#include "src/core/SkRasterPipeline.h"
+#include "src/core/SkReadBuffer.h"
+#include "src/core/SkVM.h"
+#include "src/core/SkWriteBuffer.h"
+#include "src/shaders/SkShaderBase.h"
+
+#if defined(SK_GRAPHITE)
+#include "src/gpu/graphite/KeyHelpers.h"
+#include "src/gpu/graphite/PaintParamsKey.h"
+#endif
+
+/** \class SkColorShader
+ A Shader that represents a single color. In general, this effect can be
+ accomplished by just using the color field on the paint, but if an
+ actual shader object is needed, this provides that feature.
+*/
+class SkColorShader : public SkShaderBase {
+public:
+ /** Create a ColorShader that ignores the color in the paint, and uses the
+ specified color. Note: like all shaders, at draw time the paint's alpha
+ will be respected, and is applied to the specified color.
+ */
+ explicit SkColorShader(SkColor c);
+
+ bool isOpaque() const override;
+ bool isConstant() const override { return true; }
+
+ GradientType asGradient(GradientInfo* info, SkMatrix* localMatrix) const override;
+
+#if defined(SK_GANESH)
+ std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(const GrFPArgs&,
+ const MatrixRec&) const override;
+#endif
+
+#if defined(SK_GRAPHITE)
+ void addToKey(const skgpu::graphite::KeyContext&,
+ skgpu::graphite::PaintParamsKeyBuilder*,
+ skgpu::graphite::PipelineDataGatherer*) const override;
+#endif
+
+private:
+ friend void ::SkRegisterColorShaderFlattenable();
+ SK_FLATTENABLE_HOOKS(SkColorShader)
+
+ void flatten(SkWriteBuffer&) const override;
+
+ bool onAsLuminanceColor(SkColor* lum) const override {
+ *lum = fColor;
+ return true;
+ }
+
+ bool appendStages(const SkStageRec&, const MatrixRec&) const override;
+
+ skvm::Color program(skvm::Builder*,
+ skvm::Coord device,
+ skvm::Coord local,
+ skvm::Color paint,
+ const MatrixRec&,
+ const SkColorInfo& dst,
+ skvm::Uniforms* uniforms,
+ SkArenaAlloc*) const override;
+
+ SkColor fColor;
+};
+
+class SkColor4Shader : public SkShaderBase {
+public:
+ SkColor4Shader(const SkColor4f&, sk_sp<SkColorSpace>);
+
+ bool isOpaque() const override { return fColor.isOpaque(); }
+ bool isConstant() const override { return true; }
+
+#if defined(SK_GANESH)
+ std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(const GrFPArgs&,
+ const MatrixRec&) const override;
+#endif
+#if defined(SK_GRAPHITE)
+ void addToKey(const skgpu::graphite::KeyContext&,
+ skgpu::graphite::PaintParamsKeyBuilder*,
+ skgpu::graphite::PipelineDataGatherer*) const override;
+#endif
+
+private:
+ friend void ::SkRegisterColor4ShaderFlattenable();
+ SK_FLATTENABLE_HOOKS(SkColor4Shader)
+
+ void flatten(SkWriteBuffer&) const override;
+ bool appendStages(const SkStageRec&, const MatrixRec&) const override;
+
+ skvm::Color program(skvm::Builder*,
+ skvm::Coord device,
+ skvm::Coord local,
+ skvm::Color paint,
+ const MatrixRec&,
+ const SkColorInfo& dst,
+ skvm::Uniforms* uniforms,
+ SkArenaAlloc*) const override;
+
+ sk_sp<SkColorSpace> fColorSpace;
+ const SkColor4f fColor;
+};
+
+SkColorShader::SkColorShader(SkColor c) : fColor(c) {}
+
+bool SkColorShader::isOpaque() const {
+ return SkColorGetA(fColor) == 255;
+}
+
+sk_sp<SkFlattenable> SkColorShader::CreateProc(SkReadBuffer& buffer) {
+ return sk_make_sp<SkColorShader>(buffer.readColor());
+}
+
+void SkColorShader::flatten(SkWriteBuffer& buffer) const {
+ buffer.writeColor(fColor);
+}
+
+SkShaderBase::GradientType SkColorShader::asGradient(GradientInfo* info,
+ SkMatrix* localMatrix) const {
+ if (info) {
+ if (info->fColors && info->fColorCount >= 1) {
+ info->fColors[0] = fColor;
+ }
+ info->fColorCount = 1;
+ info->fTileMode = SkTileMode::kRepeat;
+ }
+ if (localMatrix) {
+ *localMatrix = SkMatrix::I();
+ }
+ return GradientType::kColor;
+}
+
+SkColor4Shader::SkColor4Shader(const SkColor4f& color, sk_sp<SkColorSpace> space)
+ : fColorSpace(std::move(space))
+ , fColor({color.fR, color.fG, color.fB, SkTPin(color.fA, 0.0f, 1.0f)})
+{}
+
+sk_sp<SkFlattenable> SkColor4Shader::CreateProc(SkReadBuffer& buffer) {
+ SkColor4f color;
+ sk_sp<SkColorSpace> colorSpace;
+ buffer.readColor4f(&color);
+ if (buffer.readBool()) {
+ sk_sp<SkData> data = buffer.readByteArrayAsData();
+ colorSpace = data ? SkColorSpace::Deserialize(data->data(), data->size()) : nullptr;
+ }
+ return SkShaders::Color(color, std::move(colorSpace));
+}
+
+void SkColor4Shader::flatten(SkWriteBuffer& buffer) const {
+ buffer.writeColor4f(fColor);
+ sk_sp<SkData> colorSpaceData = fColorSpace ? fColorSpace->serialize() : nullptr;
+ if (colorSpaceData) {
+ buffer.writeBool(true);
+ buffer.writeDataAsByteArray(colorSpaceData.get());
+ } else {
+ buffer.writeBool(false);
+ }
+}
+
+bool SkColorShader::appendStages(const SkStageRec& rec, const MatrixRec&) const {
+ SkColor4f color = SkColor4f::FromColor(fColor);
+ SkColorSpaceXformSteps(sk_srgb_singleton(), kUnpremul_SkAlphaType,
+ rec.fDstCS, kUnpremul_SkAlphaType).apply(color.vec());
+ rec.fPipeline->append_constant_color(rec.fAlloc, color.premul().vec());
+ return true;
+}
+
+bool SkColor4Shader::appendStages(const SkStageRec& rec, const MatrixRec&) const {
+ SkColor4f color = fColor;
+ SkColorSpaceXformSteps(fColorSpace.get(), kUnpremul_SkAlphaType,
+ rec.fDstCS, kUnpremul_SkAlphaType).apply(color.vec());
+ rec.fPipeline->append_constant_color(rec.fAlloc, color.premul().vec());
+ return true;
+}
+
+skvm::Color SkColorShader::program(skvm::Builder* p,
+ skvm::Coord /*device*/,
+ skvm::Coord /*local*/,
+ skvm::Color /*paint*/,
+ const MatrixRec&,
+ const SkColorInfo& dst,
+ skvm::Uniforms* uniforms,
+ SkArenaAlloc*) const {
+ SkColor4f color = SkColor4f::FromColor(fColor);
+ SkColorSpaceXformSteps(sk_srgb_singleton(), kUnpremul_SkAlphaType,
+ dst.colorSpace(), kPremul_SkAlphaType).apply(color.vec());
+ return p->uniformColor(color, uniforms);
+}
+skvm::Color SkColor4Shader::program(skvm::Builder* p,
+ skvm::Coord /*device*/,
+ skvm::Coord /*local*/,
+ skvm::Color /*paint*/,
+ const MatrixRec&,
+ const SkColorInfo& dst,
+ skvm::Uniforms* uniforms,
+ SkArenaAlloc*) const {
+ SkColor4f color = fColor;
+ SkColorSpaceXformSteps(fColorSpace.get(), kUnpremul_SkAlphaType,
+ dst.colorSpace(), kPremul_SkAlphaType).apply(color.vec());
+ return p->uniformColor(color, uniforms);
+}
+
+#if defined(SK_GANESH)
+
+#include "src/gpu/ganesh/GrColorInfo.h"
+#include "src/gpu/ganesh/GrColorSpaceXform.h"
+#include "src/gpu/ganesh/GrFPArgs.h"
+#include "src/gpu/ganesh/GrFragmentProcessor.h"
+#include "src/gpu/ganesh/SkGr.h"
+
+std::unique_ptr<GrFragmentProcessor> SkColorShader::asFragmentProcessor(const GrFPArgs& args,
+ const MatrixRec&) const {
+ return GrFragmentProcessor::MakeColor(SkColorToPMColor4f(fColor, *args.fDstColorInfo));
+}
+
+std::unique_ptr<GrFragmentProcessor> SkColor4Shader::asFragmentProcessor(const GrFPArgs& args,
+ const MatrixRec&) const {
+ SkColorSpaceXformSteps steps{ fColorSpace.get(), kUnpremul_SkAlphaType,
+ args.fDstColorInfo->colorSpace(), kUnpremul_SkAlphaType };
+ SkColor4f color = fColor;
+ steps.apply(color.vec());
+ return GrFragmentProcessor::MakeColor(color.premul());
+}
+
+#endif
+
+#if defined(SK_GRAPHITE)
+void SkColorShader::addToKey(const skgpu::graphite::KeyContext& keyContext,
+ skgpu::graphite::PaintParamsKeyBuilder* builder,
+ skgpu::graphite::PipelineDataGatherer* gatherer) const {
+ using namespace skgpu::graphite;
+
+ SolidColorShaderBlock::BeginBlock(keyContext, builder, gatherer,
+ SkColor4f::FromColor(fColor).premul());
+ builder->endBlock();
+}
+
+void SkColor4Shader::addToKey(const skgpu::graphite::KeyContext& keyContext,
+ skgpu::graphite::PaintParamsKeyBuilder* builder,
+ skgpu::graphite::PipelineDataGatherer* gatherer) const {
+ using namespace skgpu::graphite;
+
+ SolidColorShaderBlock::BeginBlock(keyContext, builder, gatherer, fColor.premul());
+ builder->endBlock();
+}
+#endif
+
+sk_sp<SkShader> SkShaders::Color(SkColor color) { return sk_make_sp<SkColorShader>(color); }
+
+sk_sp<SkShader> SkShaders::Color(const SkColor4f& color, sk_sp<SkColorSpace> space) {
+ if (!SkScalarsAreFinite(color.vec(), 4)) {
+ return nullptr;
+ }
+ return sk_make_sp<SkColor4Shader>(color, std::move(space));
+}
+
+void SkRegisterColor4ShaderFlattenable() {
+ SK_REGISTER_FLATTENABLE(SkColor4Shader);
+}
+
+void SkRegisterColorShaderFlattenable() {
+ SK_REGISTER_FLATTENABLE(SkColorShader);
+}