aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Florin Malita <fmalita@chromium.org>2017-10-31 11:33:49 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-10-31 17:43:34 +0000
commit39d71dec606781037839faf49a9be25be7560bf1 (patch)
tree1b2880900084c510958edca4ded2951af52d506e /src
parentb7ea3da8cf722e017661710f25a83babd745a04d (diff)
Don't store legacy colors in gradient shaders
We only pass linear/4f colors to the ctor, and then derive the legacy colors from them. Might as well just derive when needed. Change-Id: I82b3d159da91f6faa4a3e7d681763c0ec1cdab07 Reviewed-on: https://skia-review.googlesource.com/65680 Commit-Queue: Florin Malita <fmalita@chromium.org> Reviewed-by: Brian Osman <brianosman@google.com>
Diffstat (limited to 'src')
-rw-r--r--src/shaders/gradients/SkGradientShader.cpp74
-rw-r--r--src/shaders/gradients/SkGradientShaderPriv.h23
-rw-r--r--src/shaders/gradients/SkLinearGradient.cpp5
-rw-r--r--src/shaders/gradients/SkRadialGradient.cpp5
-rw-r--r--src/shaders/gradients/SkSweepGradient.cpp7
-rw-r--r--src/shaders/gradients/SkTwoPointConicalGradient.cpp5
6 files changed, 65 insertions, 54 deletions
diff --git a/src/shaders/gradients/SkGradientShader.cpp b/src/shaders/gradients/SkGradientShader.cpp
index 279491b177..8b22430e91 100644
--- a/src/shaders/gradients/SkGradientShader.cpp
+++ b/src/shaders/gradients/SkGradientShader.cpp
@@ -8,6 +8,7 @@
#include <algorithm>
#include "Sk4fLinearGradient.h"
#include "SkColorSpace_XYZ.h"
+#include "SkColorSpaceXformer.h"
#include "SkFloatBits.h"
#include "SkGradientBitmapCache.h"
#include "SkGradientShaderPriv.h"
@@ -117,6 +118,7 @@ bool SkGradientShaderBase::DescriptorScope::unflatten(SkReadBuffer& buffer) {
SkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc, const SkMatrix& ptsToUnit)
: INHERITED(desc.fLocalMatrix)
, fPtsToUnit(ptsToUnit)
+ , fColorsAreOpaque(true)
{
fPtsToUnit.getType(); // Precache so reads are threadsafe.
SkASSERT(desc.fCount > 1);
@@ -148,37 +150,30 @@ SkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc, const SkMatri
}
if (fColorCount > kColorStorageCount) {
- size_t size = sizeof(SkColor) + sizeof(SkColor4f);
+ size_t size = sizeof(SkColor4f);
if (desc.fPos) {
size += sizeof(SkScalar);
}
- fOrigColors = reinterpret_cast<SkColor*>(sk_malloc_throw(size * fColorCount));
+ fOrigColors4f = reinterpret_cast<SkColor4f*>(sk_malloc_throw(size * fColorCount));
}
else {
- fOrigColors = fStorage;
+ fOrigColors4f = fStorage;
}
- fOrigColors4f = (SkColor4f*)(fOrigColors + fColorCount);
-
// Now copy over the colors, adding the dummies as needed
SkColor4f* origColors = fOrigColors4f;
if (dummyFirst) {
*origColors++ = desc.fColors[0];
}
- memcpy(origColors, desc.fColors, desc.fCount * sizeof(SkColor4f));
+ for (int i = 0; i < desc.fCount; ++i) {
+ origColors[i] = desc.fColors[i];
+ fColorsAreOpaque = fColorsAreOpaque && (desc.fColors[i].fA == 1);
+ }
if (dummyLast) {
origColors += desc.fCount;
*origColors = desc.fColors[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 the common case (sRGB colors), this does the right thing.
- for (int i = 0; i < fColorCount; ++i) {
- fOrigColors[i] = fOrigColors4f[i].toSkColor();
- }
-
if (!desc.fColorSpace) {
// This happens if we were constructed from SkColors, so our colors are really sRGB
fColorSpace = SkColorSpace::MakeSRGBLinear();
@@ -221,21 +216,12 @@ SkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc, const SkMatri
fOrigPos = nullptr;
}
}
- this->initCommon();
}
SkGradientShaderBase::~SkGradientShaderBase() {
- if (fOrigColors != fStorage) {
- sk_free(fOrigColors);
- }
-}
-
-void SkGradientShaderBase::initCommon() {
- unsigned colorAlpha = 0xFF;
- for (int i = 0; i < fColorCount; i++) {
- colorAlpha &= SkColorGetA(fOrigColors[i]);
+ if (fOrigColors4f != fStorage) {
+ sk_free(fOrigColors4f);
}
- fColorsAreOpaque = colorAlpha == 0xFF;
}
void SkGradientShaderBase::flatten(SkWriteBuffer& buffer) const {
@@ -451,8 +437,9 @@ bool SkGradientShaderBase::onAsLuminanceColor(SkColor* lum) const {
int g = 0;
int b = 0;
const int n = fColorCount;
+ // TODO: use linear colors?
for (int i = 0; i < n; ++i) {
- SkColor c = fOrigColors[i];
+ SkColor c = this->getLegacyColor(i);
r += SkColorGetR(c);
g += SkColorGetG(c);
b += SkColorGetB(c);
@@ -461,6 +448,19 @@ bool SkGradientShaderBase::onAsLuminanceColor(SkColor* lum) const {
return true;
}
+SkGradientShaderBase::AutoXformColors::AutoXformColors(const SkGradientShaderBase& grad,
+ SkColorSpaceXformer* xformer)
+ : fColors(grad.fColorCount) {
+ // TODO: stay in 4f to preserve precision?
+
+ SkAutoSTMalloc<8, SkColor> origColors(grad.fColorCount);
+ for (int i = 0; i < grad.fColorCount; ++i) {
+ origColors[i] = grad.getLegacyColor(i);
+ }
+
+ xformer->apply(fColors.get(), origColors.get(), grad.fColorCount);
+}
+
static constexpr int kGradientTextureSize = 256;
void SkGradientShaderBase::initLinearBitmap(SkBitmap* bitmap, GradientBitmapType bitmapType) const {
@@ -532,7 +532,7 @@ void SkGradientShaderBase::initLinearBitmap(SkBitmap* bitmap, GradientBitmapType
SkColor4f SkGradientShaderBase::getXformedColor(size_t i, SkColorSpace* dstCS) const {
return dstCS ? to_colorspace(fOrigColors4f[i], fColorSpace.get(), dstCS)
- : SkColor4f_from_SkColor(fOrigColors[i], nullptr);
+ : SkColor4f_from_SkColor(this->getLegacyColor(i), nullptr);
}
SK_DECLARE_STATIC_MUTEX(gGradientCacheMutex);
@@ -546,17 +546,19 @@ SK_DECLARE_STATIC_MUTEX(gGradientCacheMutex);
void SkGradientShaderBase::getGradientTableBitmap(SkBitmap* bitmap,
GradientBitmapType bitmapType) const {
// build our key: [numColors + colors[] + {positions[]} + flags + colorType ]
- int count = 1 + fColorCount + 1 + 1;
+ static_assert(sizeof(SkColor4f) % sizeof(int32_t) == 0, "");
+ const int colorsAsIntCount = fColorCount * sizeof(SkColor4f) / sizeof(int32_t);
+ int count = 1 + colorsAsIntCount + 1 + 1;
if (fColorCount > 2) {
count += fColorCount - 1;
}
- SkAutoSTMalloc<16, int32_t> storage(count);
+ SkAutoSTMalloc<64, int32_t> storage(count);
int32_t* buffer = storage.get();
*buffer++ = fColorCount;
- memcpy(buffer, fOrigColors, fColorCount * sizeof(SkColor));
- buffer += fColorCount;
+ memcpy(buffer, fOrigColors4f, fColorCount * sizeof(SkColor4f));
+ buffer += colorsAsIntCount;
if (fColorCount > 2) {
for (int i = 1; i < fColorCount; i++) {
*buffer++ = SkFloat2Bits(this->getPos(i));
@@ -608,7 +610,9 @@ void SkGradientShaderBase::commonAsAGradient(GradientInfo* info) const {
if (info) {
if (info->fColorCount >= fColorCount) {
if (info->fColors) {
- memcpy(info->fColors, fOrigColors, fColorCount * sizeof(SkColor));
+ for (int i = 0; i < fColorCount; ++i) {
+ info->fColors[i] = this->getLegacyColor(i);
+ }
}
if (info->fColorOffsets) {
for (int i = 0; i < fColorCount; ++i) {
@@ -628,7 +632,7 @@ void SkGradientShaderBase::toString(SkString* str) const {
str->appendf("%d colors: ", fColorCount);
for (int i = 0; i < fColorCount; ++i) {
- str->appendHex(fOrigColors[i], 8);
+ str->appendHex(this->getLegacyColor(i), 8);
if (i < fColorCount-1) {
str->append(", ");
}
@@ -1267,13 +1271,13 @@ GrGradientEffect::GrGradientEffect(ClassID classID, const CreateArgs& args, bool
auto colorSpaceXform = GrColorSpaceXform::Make(shader.fColorSpace.get(),
kRGBA_float_GrPixelConfig,
args.fDstColorSpace);
- SkASSERT(shader.fOrigColors && shader.fOrigColors4f);
+ SkASSERT(shader.fOrigColors4f);
fColors4f.setCount(shader.fColorCount);
for (int i = 0; i < shader.fColorCount; ++i) {
if (args.fDstColorSpace) {
fColors4f[i] = GrColor4f::FromSkColor4f(shader.fOrigColors4f[i]);
} else {
- GrColor grColor = SkColorToUnpremulGrColor(shader.fOrigColors[i]);
+ GrColor grColor = SkColorToUnpremulGrColor(shader.getLegacyColor(i));
fColors4f[i] = GrColor4f::FromGrColor(grColor);
}
diff --git a/src/shaders/gradients/SkGradientShaderPriv.h b/src/shaders/gradients/SkGradientShaderPriv.h
index 0d8e7bef9a..7084dc67b8 100644
--- a/src/shaders/gradients/SkGradientShaderPriv.h
+++ b/src/shaders/gradients/SkGradientShaderPriv.h
@@ -15,8 +15,10 @@
#include "SkMatrix.h"
#include "SkShaderBase.h"
#include "SkTDArray.h"
+#include "SkTemplates.h"
class SkColorSpace;
+class SkColorSpaceXformer;
class SkRasterPipeline;
class SkReadBuffer;
class SkWriteBuffer;
@@ -105,6 +107,12 @@ protected:
return ctx;
}
+ struct AutoXformColors {
+ AutoXformColors(const SkGradientShaderBase&, SkColorSpaceXformer*);
+
+ SkAutoSTMalloc<8, SkColor> fColors;
+ };
+
const SkMatrix fPtsToUnit;
TileMode fTileMode;
uint8_t fGradFlags;
@@ -113,20 +121,25 @@ private:
enum {
kColorStorageCount = 4, // more than this many colors, and we'll use sk_malloc for the space
- kStorageSize = kColorStorageCount * (sizeof(SkColor) + sizeof(SkScalar) + sizeof(SkColor4f))
+ kStorageSize = kColorStorageCount * (sizeof(SkColor4f) + sizeof(SkScalar))
};
- SkColor fStorage[(kStorageSize + 3) >> 2];
+ SkColor4f fStorage[(kStorageSize + sizeof(SkColor4f) - 1) / sizeof(SkColor4f)];
+
public:
SkScalar getPos(int i) const {
SkASSERT(i < fColorCount);
return fOrigPos ? fOrigPos[i] : SkIntToScalar(i) / (fColorCount - 1);
}
- SkColor* fOrigColors; // original colors, before modulation by paint in context.
+ SkColor getLegacyColor(int i) const {
+ SkASSERT(i < fColorCount);
+ return fOrigColors4f[i].toSkColor();
+ }
+
SkColor4f* fOrigColors4f; // original colors, as linear floats
SkScalar* fOrigPos; // original positions
int fColorCount;
- sk_sp<SkColorSpace> fColorSpace; // color space of gradient stops
+ sk_sp<SkColorSpace> fColorSpace; // color space of gradient stops
bool colorsAreOpaque() const { return fColorsAreOpaque; }
@@ -135,8 +148,6 @@ public:
private:
bool fColorsAreOpaque;
- void initCommon();
-
typedef SkShaderBase INHERITED;
};
diff --git a/src/shaders/gradients/SkLinearGradient.cpp b/src/shaders/gradients/SkLinearGradient.cpp
index 3b41e79710..4932679890 100644
--- a/src/shaders/gradients/SkLinearGradient.cpp
+++ b/src/shaders/gradients/SkLinearGradient.cpp
@@ -72,10 +72,9 @@ void SkLinearGradient::appendGradientStages(SkArenaAlloc*, SkRasterPipeline*,
}
sk_sp<SkShader> SkLinearGradient::onMakeColorSpace(SkColorSpaceXformer* xformer) const {
+ const AutoXformColors xformedColors(*this, xformer);
SkPoint pts[2] = { fStart, fEnd };
- SkSTArray<8, SkColor> xformedColors(fColorCount);
- xformer->apply(xformedColors.begin(), fOrigColors, fColorCount);
- return SkGradientShader::MakeLinear(pts, xformedColors.begin(), fOrigPos, fColorCount,
+ return SkGradientShader::MakeLinear(pts, xformedColors.fColors.get(), fOrigPos, fColorCount,
fTileMode, fGradFlags, &this->getLocalMatrix());
}
diff --git a/src/shaders/gradients/SkRadialGradient.cpp b/src/shaders/gradients/SkRadialGradient.cpp
index 5014eaea75..0dede71001 100644
--- a/src/shaders/gradients/SkRadialGradient.cpp
+++ b/src/shaders/gradients/SkRadialGradient.cpp
@@ -196,9 +196,8 @@ std::unique_ptr<GrFragmentProcessor> SkRadialGradient::asFragmentProcessor(
#endif
sk_sp<SkShader> SkRadialGradient::onMakeColorSpace(SkColorSpaceXformer* xformer) const {
- SkSTArray<8, SkColor> xformedColors(fColorCount);
- xformer->apply(xformedColors.begin(), fOrigColors, fColorCount);
- return SkGradientShader::MakeRadial(fCenter, fRadius, xformedColors.begin(), fOrigPos,
+ const AutoXformColors xformedColors(*this, xformer);
+ return SkGradientShader::MakeRadial(fCenter, fRadius, xformedColors.fColors.get(), fOrigPos,
fColorCount, fTileMode, fGradFlags,
&this->getLocalMatrix());
}
diff --git a/src/shaders/gradients/SkSweepGradient.cpp b/src/shaders/gradients/SkSweepGradient.cpp
index 75622217b4..1f24680476 100644
--- a/src/shaders/gradients/SkSweepGradient.cpp
+++ b/src/shaders/gradients/SkSweepGradient.cpp
@@ -251,14 +251,13 @@ std::unique_ptr<GrFragmentProcessor> SkSweepGradient::asFragmentProcessor(
#endif
sk_sp<SkShader> SkSweepGradient::onMakeColorSpace(SkColorSpaceXformer* xformer) const {
- SkSTArray<8, SkColor> xformedColors(fColorCount);
- xformer->apply(xformedColors.begin(), fOrigColors, fColorCount);
+ const AutoXformColors xformedColors(*this, xformer);
SkScalar startAngle, endAngle;
std::tie(startAngle, endAngle) = angles_from_t_coeff(fTBias, fTScale);
- return SkGradientShader::MakeSweep(fCenter.fX, fCenter.fY, xformedColors.begin(), fOrigPos,
- fColorCount, fTileMode, startAngle, endAngle,
+ return SkGradientShader::MakeSweep(fCenter.fX, fCenter.fY, xformedColors.fColors.get(),
+ fOrigPos, fColorCount, fTileMode, startAngle, endAngle,
fGradFlags, &this->getLocalMatrix());
}
diff --git a/src/shaders/gradients/SkTwoPointConicalGradient.cpp b/src/shaders/gradients/SkTwoPointConicalGradient.cpp
index 86625de41e..cd7bbb1252 100644
--- a/src/shaders/gradients/SkTwoPointConicalGradient.cpp
+++ b/src/shaders/gradients/SkTwoPointConicalGradient.cpp
@@ -140,10 +140,9 @@ std::unique_ptr<GrFragmentProcessor> SkTwoPointConicalGradient::asFragmentProces
#endif
sk_sp<SkShader> SkTwoPointConicalGradient::onMakeColorSpace(SkColorSpaceXformer* xformer) const {
- SkSTArray<8, SkColor> xformedColors(fColorCount);
- xformer->apply(xformedColors.begin(), fOrigColors, fColorCount);
+ const AutoXformColors xformedColors(*this, xformer);
return SkGradientShader::MakeTwoPointConical(fCenter1, fRadius1, fCenter2, fRadius2,
- xformedColors.begin(), fOrigPos, fColorCount,
+ xformedColors.fColors.get(), fOrigPos, fColorCount,
fTileMode, fGradFlags, &this->getLocalMatrix());
}