| Index: src/effects/gradients/SkGradientShader.cpp
|
| diff --git a/src/effects/gradients/SkGradientShader.cpp b/src/effects/gradients/SkGradientShader.cpp
|
| index 14e67842b337b3addb15f45e51630fae65541c52..60767f876d2ea4b69f396ad3bd08531ea2ed9488 100644
|
| --- a/src/effects/gradients/SkGradientShader.cpp
|
| +++ b/src/effects/gradients/SkGradientShader.cpp
|
| @@ -14,6 +14,7 @@
|
|
|
| void SkGradientShaderBase::Descriptor::flatten(SkWriteBuffer& buffer) const {
|
| buffer.writeColorArray(fColors, fCount);
|
| + // TODO: Flatten fColors4f and fColorSpace
|
| if (fPos) {
|
| buffer.writeBool(true);
|
| buffer.writeScalarArray(fPos, fCount);
|
| @@ -31,6 +32,7 @@ void SkGradientShaderBase::Descriptor::flatten(SkWriteBuffer& buffer) const {
|
| }
|
|
|
| bool SkGradientShaderBase::DescriptorScope::unflatten(SkReadBuffer& buffer) {
|
| + // TODO: Unflatten fColors4f and fColorSpace
|
| fCount = buffer.getArrayCount();
|
| if (fCount > kStorageCount) {
|
| size_t allocSize = (sizeof(SkColor) + sizeof(SkScalar)) * fCount;
|
| @@ -103,7 +105,7 @@ SkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc, const SkMatri
|
| }
|
|
|
| if (fColorCount > kColorStorageCount) {
|
| - size_t size = sizeof(SkColor) + sizeof(Rec);
|
| + size_t size = sizeof(SkColor) + sizeof(SkColor4f) + sizeof(Rec);
|
| if (desc.fPos) {
|
| size += sizeof(SkScalar);
|
| }
|
| @@ -114,8 +116,14 @@ SkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc, const SkMatri
|
| fOrigColors = fStorage;
|
| }
|
|
|
| - // Now copy over the colors, adding the dummies as needed
|
| - {
|
| + fOrigColors4f = (SkColor4f*)(fOrigColors + fColorCount);
|
| +
|
| + // We should have been supplied with either fColors *or* (fColors4f and fColorSpace)
|
| + if (desc.fColors) {
|
| + // TODO: Should we support alternate gamma-encoded colorspaces with SkColor inputs?
|
| + SkASSERT(!desc.fColors4f && !desc.fColorSpace);
|
| +
|
| + // Now copy over the colors, adding the dummies as needed
|
| SkColor* origColors = fOrigColors;
|
| if (dummyFirst) {
|
| *origColors++ = desc.fColors[0];
|
| @@ -125,14 +133,44 @@ SkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc, const SkMatri
|
| origColors += desc.fCount;
|
| *origColors = desc.fColors[desc.fCount - 1];
|
| }
|
| +
|
| + // Convert our SkColor colors to SkColor4f as well
|
| + for (int i = 0; i < fColorCount; ++i) {
|
| + fOrigColors4f[i] = SkColor4f::FromColor(fOrigColors[i]);
|
| + }
|
| +
|
| + // Color space refers to fColors4f, so it's always linear gamma
|
| + fColorSpace = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named)->makeLinearGamma();
|
| + } else {
|
| + SkASSERT(desc.fColors4f && desc.fColorSpace && desc.fColorSpace->gammaIsLinear());
|
| +
|
| + // Now copy over the colors, adding the dummies as needed
|
| + SkColor4f* origColors = fOrigColors4f;
|
| + if (dummyFirst) {
|
| + *origColors++ = desc.fColors4f[0];
|
| + }
|
| + memcpy(origColors, desc.fColors4f, desc.fCount * sizeof(SkColor4f));
|
| + if (dummyLast) {
|
| + origColors += desc.fCount;
|
| + *origColors = desc.fColors4f[desc.fCount - 1];
|
| + }
|
| +
|
| + // Convert our SkColor4f colors to SkColor as well. Note that this is incorrect if the
|
| + // source colors are not in sRGB gamut. We would need to do a gamut transformation, but
|
| + // SkColorSpaceXform can't do that (yet). GrColorSpaceXform can, but we may not have GPU
|
| + // support compiled in here.
|
| + for (int i = 0; i < fColorCount; ++i) {
|
| + fOrigColors[i] = fOrigColors4f[i].toSkColor();
|
| + }
|
| + fColorSpace = desc.fColorSpace;
|
| }
|
|
|
| if (desc.fPos && fColorCount) {
|
| - fOrigPos = (SkScalar*)(fOrigColors + fColorCount);
|
| + fOrigPos = (SkScalar*)(fOrigColors4f + fColorCount);
|
| fRecs = (Rec*)(fOrigPos + fColorCount);
|
| } else {
|
| fOrigPos = nullptr;
|
| - fRecs = (Rec*)(fOrigColors + fColorCount);
|
| + fRecs = (Rec*)(fOrigColors4f + fColorCount);
|
| }
|
|
|
| if (fColorCount > 2) {
|
| @@ -218,6 +256,8 @@ void SkGradientShaderBase::initCommon() {
|
| void SkGradientShaderBase::flatten(SkWriteBuffer& buffer) const {
|
| Descriptor desc;
|
| desc.fColors = fOrigColors;
|
| + desc.fColors4f = fOrigColors4f;
|
| + desc.fColorSpace = fColorSpace;
|
| desc.fPos = fOrigPos;
|
| desc.fCount = fColorCount;
|
| desc.fTileMode = fTileMode;
|
| @@ -748,6 +788,8 @@ static void desc_init(SkGradientShaderBase::Descriptor* desc,
|
| SkASSERT(colorCount > 1);
|
|
|
| desc->fColors = colors;
|
| + desc->fColors4f = nullptr;
|
| + desc->fColorSpace = nullptr; // SkColor is always sRGB
|
| desc->fPos = pos;
|
| desc->fCount = colorCount;
|
| desc->fTileMode = mode;
|
| @@ -1032,6 +1074,52 @@ void GrGradientEffect::GLSLProcessor::emitUniforms(GrGLSLUniformHandler* uniform
|
| }
|
| }
|
|
|
| +static inline void set_after_interp_color_uni_array(
|
| + const GrGLSLProgramDataManager& pdman,
|
| + const GrGLSLProgramDataManager::UniformHandle uni,
|
| + const SkTDArray<SkColor4f>& colors,
|
| + const GrColorSpaceXform* colorSpaceXform) {
|
| + int count = colors.count();
|
| + if (colorSpaceXform) {
|
| + constexpr int kSmallCount = 10;
|
| + SkAutoSTArray<4 * kSmallCount, float> vals(4 * count);
|
| +
|
| + for (int i = 0; i < count; i++) {
|
| + colorSpaceXform->srcToDst().mapScalars(colors[i].vec(), &vals[4 * i]);
|
| + }
|
| +
|
| + pdman.set4fv(uni, count, vals.get());
|
| + } else {
|
| + pdman.set4fv(uni, count, (float*)&colors[0]);
|
| + }
|
| +}
|
| +
|
| +static inline void set_before_interp_color_uni_array(
|
| + const GrGLSLProgramDataManager& pdman,
|
| + const GrGLSLProgramDataManager::UniformHandle uni,
|
| + const SkTDArray<SkColor4f>& colors,
|
| + const GrColorSpaceXform* colorSpaceXform) {
|
| + int count = colors.count();
|
| + constexpr int kSmallCount = 10;
|
| + SkAutoSTArray<4 * kSmallCount, float> vals(4 * count);
|
| +
|
| + for (int i = 0; i < count; i++) {
|
| + float a = colors[i].fA;
|
| + vals[4 * i + 0] = colors[i].fR * a;
|
| + vals[4 * i + 1] = colors[i].fG * a;
|
| + vals[4 * i + 2] = colors[i].fB * a;
|
| + vals[4 * i + 3] = a;
|
| + }
|
| +
|
| + if (colorSpaceXform) {
|
| + for (int i = 0; i < count; i++) {
|
| + colorSpaceXform->srcToDst().mapScalars(&vals[4 * i]);
|
| + }
|
| + }
|
| +
|
| + pdman.set4fv(uni, count, vals.get());
|
| +}
|
| +
|
| static inline void set_after_interp_color_uni_array(const GrGLSLProgramDataManager& pdman,
|
| const GrGLSLProgramDataManager::UniformHandle uni,
|
| const SkTDArray<SkColor>& colors) {
|
| @@ -1085,10 +1173,22 @@ void GrGradientEffect::GLSLProcessor::onSetData(const GrGLSLProgramDataManager&
|
| #endif
|
| case GrGradientEffect::kTwo_ColorType:
|
| case GrGradientEffect::kThree_ColorType: {
|
| - if (GrGradientEffect::kBeforeInterp_PremulType == e.getPremulType()) {
|
| - set_before_interp_color_uni_array(pdman, fColorsUni, e.fColors);
|
| + if (e.fColors4f.count() > 0) {
|
| + // Gamma-correct / color-space aware
|
| + if (GrGradientEffect::kBeforeInterp_PremulType == e.getPremulType()) {
|
| + set_before_interp_color_uni_array(pdman, fColorsUni, e.fColors4f,
|
| + e.fColorSpaceXform.get());
|
| + } else {
|
| + set_after_interp_color_uni_array(pdman, fColorsUni, e.fColors4f,
|
| + e.fColorSpaceXform.get());
|
| + }
|
| } else {
|
| - set_after_interp_color_uni_array(pdman, fColorsUni, e.fColors);
|
| + // Legacy mode. Would be nice if we had converted the 8-bit colors to float earlier
|
| + if (GrGradientEffect::kBeforeInterp_PremulType == e.getPremulType()) {
|
| + set_before_interp_color_uni_array(pdman, fColorsUni, e.fColors);
|
| + } else {
|
| + set_after_interp_color_uni_array(pdman, fColorsUni, e.fColors);
|
| + }
|
| }
|
|
|
| break;
|
| @@ -1340,7 +1440,11 @@ GrGradientEffect::GrGradientEffect(const CreateArgs& args) {
|
| fColorType = this->determineColorType(shader);
|
|
|
| if (kTexture_ColorType != fColorType) {
|
| - if (shader.fOrigColors) {
|
| + SkASSERT(shader.fOrigColors && shader.fOrigColors4f);
|
| + if (args.fGammaCorrect) {
|
| + fColors4f = SkTDArray<SkColor4f>(shader.fOrigColors4f, shader.fColorCount);
|
| + fColorSpaceXform = std::move(args.fColorSpaceXform);
|
| + } else {
|
| fColors = SkTDArray<SkColor>(shader.fOrigColors, shader.fColorCount);
|
| }
|
|
|
| @@ -1440,7 +1544,8 @@ bool GrGradientEffect::onIsEqual(const GrFragmentProcessor& processor) const {
|
| }
|
| } else {
|
| if (this->getPremulType() != ge.getPremulType() ||
|
| - this->fColors.count() != ge.fColors.count()) {
|
| + this->fColors.count() != ge.fColors.count() ||
|
| + this->fColors4f.count() != ge.fColors4f.count()) {
|
| return false;
|
| }
|
|
|
| @@ -1449,10 +1554,16 @@ bool GrGradientEffect::onIsEqual(const GrFragmentProcessor& processor) const {
|
| return false;
|
| }
|
| }
|
| + for (int i = 0; i < this->fColors4f.count(); i++) {
|
| + if (*this->getColors4f(i) != *ge.getColors4f(i)) {
|
| + return false;
|
| + }
|
| + }
|
| }
|
|
|
| +
|
| SkASSERT(this->useAtlas() == ge.useAtlas());
|
| - return true;
|
| + return GrColorSpaceXform::Equals(this->fColorSpaceXform.get(), ge.fColorSpaceXform.get());
|
| }
|
|
|
| return false;
|
|
|