blob: 75668a8f7f46447fc587f446c1a5ef6a369411d0 [file] [log] [blame]
reed0ccc62d2016-05-04 13:09:39 -07001/*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "include/core/SkColorSpace.h"
Ben Wagner729a23f2019-05-17 16:29:34 -04009#include "src/core/SkArenaAlloc.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "src/core/SkColorSpacePriv.h"
11#include "src/core/SkColorSpaceXformSteps.h"
12#include "src/core/SkRasterPipeline.h"
13#include "src/core/SkReadBuffer.h"
14#include "src/core/SkUtils.h"
15#include "src/shaders/SkColorShader.h"
reed0ccc62d2016-05-04 13:09:39 -070016
17SkColorShader::SkColorShader(SkColor c) : fColor(c) {}
18
19bool SkColorShader::isOpaque() const {
20 return SkColorGetA(fColor) == 255;
21}
22
23sk_sp<SkFlattenable> SkColorShader::CreateProc(SkReadBuffer& buffer) {
24 return sk_make_sp<SkColorShader>(buffer.readColor());
25}
26
27void SkColorShader::flatten(SkWriteBuffer& buffer) const {
28 buffer.writeColor(fColor);
29}
30
reed0ccc62d2016-05-04 13:09:39 -070031SkShader::GradientType SkColorShader::asAGradient(GradientInfo* info) const {
32 if (info) {
33 if (info->fColors && info->fColorCount >= 1) {
34 info->fColors[0] = fColor;
35 }
36 info->fColorCount = 1;
Mike Reedfae8fce2019-04-03 10:27:45 -040037 info->fTileMode = SkTileMode::kRepeat;
reed0ccc62d2016-05-04 13:09:39 -070038 }
39 return kColor_GradientType;
40}
41
reed0ccc62d2016-05-04 13:09:39 -070042SkColor4Shader::SkColor4Shader(const SkColor4f& color, sk_sp<SkColorSpace> space)
43 : fColorSpace(std::move(space))
Mike Kleina4eb9362018-10-30 13:36:24 -040044 , fColor(color)
reed0ccc62d2016-05-04 13:09:39 -070045{}
46
47sk_sp<SkFlattenable> SkColor4Shader::CreateProc(SkReadBuffer& buffer) {
48 SkColor4f color;
Brian Osman97d09702018-08-03 15:56:55 -040049 sk_sp<SkColorSpace> colorSpace;
brianosman97bbf822016-09-25 13:15:58 -070050 buffer.readColor4f(&color);
reed0ccc62d2016-05-04 13:09:39 -070051 if (buffer.readBool()) {
Brian Osman97d09702018-08-03 15:56:55 -040052 sk_sp<SkData> data = buffer.readByteArrayAsData();
53 colorSpace = data ? SkColorSpace::Deserialize(data->data(), data->size()) : nullptr;
reed0ccc62d2016-05-04 13:09:39 -070054 }
Mike Reedc8bea7d2019-04-09 13:55:36 -040055 return SkShaders::Color(color, std::move(colorSpace));
reed0ccc62d2016-05-04 13:09:39 -070056}
57
58void SkColor4Shader::flatten(SkWriteBuffer& buffer) const {
Mike Kleina4eb9362018-10-30 13:36:24 -040059 buffer.writeColor4f(fColor);
Brian Osman97d09702018-08-03 15:56:55 -040060 sk_sp<SkData> colorSpaceData = fColorSpace ? fColorSpace->serialize() : nullptr;
61 if (colorSpaceData) {
62 buffer.writeBool(true);
63 buffer.writeDataAsByteArray(colorSpaceData.get());
64 } else {
65 buffer.writeBool(false);
66 }
reed0ccc62d2016-05-04 13:09:39 -070067}
68
reed0ccc62d2016-05-04 13:09:39 -070069
Mike Reedc8bea7d2019-04-09 13:55:36 -040070sk_sp<SkShader> SkShaders::Color(const SkColor4f& color, sk_sp<SkColorSpace> space) {
reed0ccc62d2016-05-04 13:09:39 -070071 if (!SkScalarsAreFinite(color.vec(), 4)) {
72 return nullptr;
73 }
74 return sk_make_sp<SkColor4Shader>(color, std::move(space));
75}
76
Mike Reed1386b2d2019-03-13 21:15:05 -040077bool SkColorShader::onAppendStages(const SkStageRec& rec) const {
Brian Osman5d7b5a32018-10-26 13:05:07 -040078 SkColor4f color = SkColor4f::FromColor(fColor);
79 SkColorSpaceXformSteps(sk_srgb_singleton(), kUnpremul_SkAlphaType,
80 rec.fDstCS, kUnpremul_SkAlphaType).apply(color.vec());
81 rec.fPipeline->append_constant_color(rec.fAlloc, color.premul().vec());
Matt Sarett87345662017-03-08 13:13:58 -050082 return true;
Mike Kleinb0d10e02016-11-12 10:29:26 -050083}
84
Mike Reed1386b2d2019-03-13 21:15:05 -040085bool SkColor4Shader::onAppendStages(const SkStageRec& rec) const {
Mike Kleina4eb9362018-10-30 13:36:24 -040086 SkColor4f color = fColor;
Brian Osman5d7b5a32018-10-26 13:05:07 -040087 SkColorSpaceXformSteps(fColorSpace.get(), kUnpremul_SkAlphaType,
88 rec.fDstCS, kUnpremul_SkAlphaType).apply(color.vec());
89 rec.fPipeline->append_constant_color(rec.fAlloc, color.premul().vec());
Matt Sarett87345662017-03-08 13:13:58 -050090 return true;
Mike Kleinb0d10e02016-11-12 10:29:26 -050091}
Mike Kleina4eb9362018-10-30 13:36:24 -040092
Mike Klein9d0c67a2019-10-31 15:41:58 -050093static bool common_program(SkColor4f color, SkColorSpace* cs,
94 skvm::Builder* p,
95 SkColorSpace* dstCS,
Mike Klein1cc60672019-11-05 14:19:58 -060096 skvm::Uniforms* uniforms,
Mike Kleinb9f20882019-11-08 12:14:15 -060097 skvm::F32* r, skvm::F32* g, skvm::F32* b, skvm::F32* a) {
Mike Klein9d0c67a2019-10-31 15:41:58 -050098 SkColorSpaceXformSteps( cs, kUnpremul_SkAlphaType,
Mike Kleinb9f20882019-11-08 12:14:15 -060099 dstCS, kPremul_SkAlphaType).apply(color.vec());
Mike Kleine4522dc2019-10-29 12:10:34 -0500100
Mike Kleinb9f20882019-11-08 12:14:15 -0600101 *r = p->uniformF(uniforms->pushF(color.fR));
102 *g = p->uniformF(uniforms->pushF(color.fG));
103 *b = p->uniformF(uniforms->pushF(color.fB));
104 *a = p->uniformF(uniforms->pushF(color.fA));
105 return true;
Mike Kleine4522dc2019-10-29 12:10:34 -0500106}
Mike Kleine4522dc2019-10-29 12:10:34 -0500107
Mike Klein03935052019-11-01 11:36:55 -0500108bool SkColorShader::onProgram(skvm::Builder* p,
Mike Klein9d0c67a2019-10-31 15:41:58 -0500109 SkColorSpace* dstCS,
Mike Klein1cc60672019-11-05 14:19:58 -0600110 skvm::Uniforms* uniforms,
Mike Kleinf3d41092019-11-04 13:22:02 -0600111 skvm::F32 /*x*/, skvm::F32 /*y*/,
Mike Kleinb9f20882019-11-08 12:14:15 -0600112 skvm::F32* r, skvm::F32* g, skvm::F32* b, skvm::F32* a) const {
Mike Klein03935052019-11-01 11:36:55 -0500113 return common_program(SkColor4f::FromColor(fColor), sk_srgb_singleton(),
Mike Klein1cc60672019-11-05 14:19:58 -0600114 p, dstCS, uniforms, r,g,b,a);
Mike Klein03935052019-11-01 11:36:55 -0500115}
116bool SkColor4Shader::onProgram(skvm::Builder* p,
117 SkColorSpace* dstCS,
Mike Klein1cc60672019-11-05 14:19:58 -0600118 skvm::Uniforms* uniforms,
Mike Kleinf3d41092019-11-04 13:22:02 -0600119 skvm::F32 /*x*/, skvm::F32 /*y*/,
Mike Kleinb9f20882019-11-08 12:14:15 -0600120 skvm::F32* r, skvm::F32* g, skvm::F32* b, skvm::F32* a) const {
Mike Klein9d0c67a2019-10-31 15:41:58 -0500121 return common_program(fColor, fColorSpace.get(),
Mike Klein1cc60672019-11-05 14:19:58 -0600122 p, dstCS, uniforms, r,g,b,a);
Mike Klein9d0c67a2019-10-31 15:41:58 -0500123}
Mike Kleine4522dc2019-10-29 12:10:34 -0500124
Mike Kleina4eb9362018-10-30 13:36:24 -0400125#if SK_SUPPORT_GPU
126
Brian Salomon4bc0c1f2019-09-30 15:12:27 -0400127#include "src/gpu/GrColorInfo.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -0500128#include "src/gpu/GrColorSpaceXform.h"
129#include "src/gpu/SkGr.h"
130#include "src/gpu/effects/generated/GrConstColorProcessor.h"
Mike Kleina4eb9362018-10-30 13:36:24 -0400131
132std::unique_ptr<GrFragmentProcessor> SkColorShader::asFragmentProcessor(
133 const GrFPArgs& args) const {
Brian Salomon4bc0c1f2019-09-30 15:12:27 -0400134 SkPMColor4f color = SkColorToPMColor4f(fColor, *args.fDstColorInfo);
Mike Kleina4eb9362018-10-30 13:36:24 -0400135 return GrConstColorProcessor::Make(color, GrConstColorProcessor::InputMode::kModulateA);
136}
137
138std::unique_ptr<GrFragmentProcessor> SkColor4Shader::asFragmentProcessor(
139 const GrFPArgs& args) const {
Brian Salomon4bc0c1f2019-09-30 15:12:27 -0400140 SkColorSpaceXformSteps steps{ fColorSpace.get(), kUnpremul_SkAlphaType,
141 args.fDstColorInfo->colorSpace(), kUnpremul_SkAlphaType };
Mike Kleina4eb9362018-10-30 13:36:24 -0400142 SkColor4f color = fColor;
143 steps.apply(color.vec());
144 return GrConstColorProcessor::Make(color.premul(),
145 GrConstColorProcessor::InputMode::kModulateA);
146}
147
148#endif