#include "SkTwoPointConicalGradient.h"
#include "SkSweepGradient.h"
-SkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc) {
- SkASSERT(desc.fCount > 1);
+void SkGradientShaderBase::Descriptor::flatten(SkWriteBuffer& buffer) const {
+ buffer.writeColorArray(fColors, fCount);
+ if (fPos) {
+ buffer.writeBool(true);
+ buffer.writeScalarArray(fPos, fCount);
+ } else {
+ buffer.writeBool(false);
+ }
+ buffer.write32(fTileMode);
+ buffer.write32(fGradFlags);
+ if (fLocalMatrix) {
+ buffer.writeBool(true);
+ buffer.writeMatrix(*fLocalMatrix);
+ } else {
+ buffer.writeBool(false);
+ }
+}
+
+bool SkGradientShaderBase::DescriptorScope::unflatten(SkReadBuffer& buffer) {
+ fCount = buffer.getArrayCount();
+ if (fCount > kStorageCount) {
+ size_t allocSize = (sizeof(SkColor) + sizeof(SkScalar)) * fCount;
+ fDynamicStorage.reset(allocSize);
+ fColors = (SkColor*)fDynamicStorage.get();
+ fPos = (SkScalar*)(fColors + fCount);
+ } else {
+ fColors = fColorStorage;
+ fPos = fPosStorage;
+ }
- fCacheAlpha = 256; // init to a value that paint.getAlpha() can't return
+ if (!buffer.readColorArray(const_cast<SkColor*>(fColors), fCount)) {
+ return false;
+ }
+ if (buffer.readBool()) {
+ if (!buffer.readScalarArray(const_cast<SkScalar*>(fPos), fCount)) {
+ return false;
+ }
+ } else {
+ fPos = NULL;
+ }
- fMapper = desc.fMapper;
- SkSafeRef(fMapper);
- fGradFlags = SkToU8(desc.fFlags);
+ fTileMode = (SkShader::TileMode)buffer.read32();
+ fGradFlags = buffer.read32();
+
+ if (buffer.readBool()) {
+ fLocalMatrix = &fLocalMatrixStorage;
+ buffer.readMatrix(&fLocalMatrixStorage);
+ } else {
+ fLocalMatrix = NULL;
+ }
+ return buffer.isValid();
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////
+
+SkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc)
+ : INHERITED(desc.fLocalMatrix)
+{
+ SkASSERT(desc.fCount > 1);
+
+ fGradFlags = SkToU8(desc.fGradFlags);
SkASSERT((unsigned)desc.fTileMode < SkShader::kTileModeCount);
SkASSERT(SkShader::kTileModeCount == SK_ARRAY_COUNT(gTileProcs));
fTileMode = desc.fTileMode;
fTileProc = gTileProcs[desc.fTileMode];
- fCache16 = fCache16Storage = NULL;
- fCache32 = NULL;
- fCache32PixelRef = NULL;
-
/* Note: we let the caller skip the first and/or last position.
i.e. pos[0] = 0.3, pos[1] = 0.7
In these cases, we insert dummy entries to ensure that the final data
if (fColorCount > kColorStorageCount) {
size_t size = sizeof(SkColor) + sizeof(Rec);
+ if (desc.fPos) {
+ size += sizeof(SkScalar);
+ }
fOrigColors = reinterpret_cast<SkColor*>(
sk_malloc_throw(size * fColorCount));
}
}
}
- fRecs = (Rec*)(fOrigColors + fColorCount);
+ if (desc.fPos && fColorCount) {
+ fOrigPos = (SkScalar*)(fOrigColors + fColorCount);
+ fRecs = (Rec*)(fOrigPos + fColorCount);
+ } else {
+ fOrigPos = NULL;
+ fRecs = (Rec*)(fOrigColors + fColorCount);
+ }
+
if (fColorCount > 2) {
Rec* recs = fRecs;
recs->fPos = 0;
// recs->fScale = 0; // unused;
recs += 1;
if (desc.fPos) {
+ SkScalar* origPosPtr = fOrigPos;
+ *origPosPtr++ = 0;
+
/* We need to convert the user's array of relative positions into
fixed-point positions and scale factors. We need these results
to be strictly monotonic (no two values equal or out of order).
value if it sees a segment out of order, and it assures that
we start at 0 and end at 1.0
*/
- SkFixed prev = 0;
+ SkScalar prev = 0;
int startIndex = dummyFirst ? 0 : 1;
int count = desc.fCount + dummyLast;
for (int i = startIndex; i < count; i++) {
// force the last value to be 1.0
- SkFixed curr;
+ SkScalar curr;
if (i == desc.fCount) { // we're really at the dummyLast
- curr = SK_Fixed1;
+ curr = 1;
} else {
- curr = SkScalarToFixed(desc.fPos[i]);
+ curr = SkScalarPin(desc.fPos[i], 0, 1);
}
- // pin curr withing range
- if (curr < 0) {
- curr = 0;
- } else if (curr > SK_Fixed1) {
- curr = SK_Fixed1;
- }
- recs->fPos = curr;
- if (curr > prev) {
- recs->fScale = (1 << 24) / (curr - prev);
+ *origPosPtr++ = curr;
+
+ recs->fPos = SkScalarToFixed(curr);
+ SkFixed diff = SkScalarToFixed(curr - prev);
+ if (diff > 0) {
+ recs->fScale = (1 << 24) / diff;
} else {
recs->fScale = 0; // ignore this segment
}
recs += 1;
}
} else { // assume even distribution
+ fOrigPos = NULL;
+
SkFixed dp = SK_Fixed1 / (desc.fCount - 1);
SkFixed p = dp;
SkFixed scale = (desc.fCount - 1) << 8; // (1 << 24) / dp
- for (int i = 1; i < desc.fCount; i++) {
+ for (int i = 1; i < desc.fCount - 1; i++) {
recs->fPos = p;
recs->fScale = scale;
recs += 1;
p += dp;
}
+ recs->fPos = SK_Fixed1;
+ recs->fScale = scale;
+ }
+ } else if (desc.fPos) {
+ SkASSERT(2 == fColorCount);
+ fOrigPos[0] = SkScalarPin(desc.fPos[0], 0, 1);
+ fOrigPos[1] = SkScalarPin(desc.fPos[1], fOrigPos[0], 1);
+ if (0 == fOrigPos[0] && 1 == fOrigPos[1]) {
+ fOrigPos = NULL;
}
}
this->initCommon();
}
-static uint32_t pack_mode_flags(SkShader::TileMode mode, uint32_t flags) {
- SkASSERT(0 == (flags >> 28));
- SkASSERT(0 == ((uint32_t)mode >> 4));
- return (flags << 4) | mode;
-}
-
+#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
static SkShader::TileMode unpack_mode(uint32_t packed) {
return (SkShader::TileMode)(packed & 0xF);
}
}
SkGradientShaderBase::SkGradientShaderBase(SkReadBuffer& buffer) : INHERITED(buffer) {
- fCacheAlpha = 256;
-
- fMapper = buffer.readUnitMapper();
-
- fCache16 = fCache16Storage = NULL;
- fCache32 = NULL;
- fCache32PixelRef = NULL;
+ if (buffer.isVersionLT(SkReadBuffer::kNoUnitMappers_Version)) {
+ // skip the old SkUnitMapper slot
+ buffer.skipFlattenable();
+ }
int colorCount = fColorCount = buffer.getArrayCount();
if (colorCount > kColorStorageCount) {
- size_t allocSize = (sizeof(SkColor) + sizeof(SkPMColor) + sizeof(Rec)) * colorCount;
+ size_t allocSize = (sizeof(SkColor) + sizeof(SkScalar) + sizeof(Rec)) * colorCount;
if (buffer.validateAvailable(allocSize)) {
fOrigColors = reinterpret_cast<SkColor*>(sk_malloc_throw(allocSize));
} else {
}
buffer.readColorArray(fOrigColors, colorCount);
+ fOrigPos = (SkScalar*)(fOrigColors + colorCount);
+
{
uint32_t packed = buffer.readUInt();
fGradFlags = SkToU8(unpack_flags(packed));
fTileMode = unpack_mode(packed);
}
fTileProc = gTileProcs[fTileMode];
- fRecs = (Rec*)(fOrigColors + colorCount);
+ fRecs = (Rec*)(fOrigPos + colorCount);
if (colorCount > 2) {
Rec* recs = fRecs;
recs[0].fPos = 0;
+ fOrigPos[0] = 0;
for (int i = 1; i < colorCount; i++) {
recs[i].fPos = buffer.readInt();
recs[i].fScale = buffer.readUInt();
+ fOrigPos[i] = SkFixedToScalar(recs[i].fPos);
}
+ } else {
+ fOrigPos = NULL;
}
buffer.readMatrix(&fPtsToUnit);
this->initCommon();
}
+#endif
SkGradientShaderBase::~SkGradientShaderBase() {
- if (fCache16Storage) {
- sk_free(fCache16Storage);
- }
- SkSafeUnref(fCache32PixelRef);
if (fOrigColors != fStorage) {
sk_free(fOrigColors);
}
- SkSafeUnref(fMapper);
}
void SkGradientShaderBase::initCommon() {
- fFlags = 0;
unsigned colorAlpha = 0xFF;
for (int i = 0; i < fColorCount; i++) {
colorAlpha &= SkColorGetA(fOrigColors[i]);
}
void SkGradientShaderBase::flatten(SkWriteBuffer& buffer) const {
- this->INHERITED::flatten(buffer);
- buffer.writeFlattenable(fMapper);
- buffer.writeColorArray(fOrigColors, fColorCount);
- buffer.writeUInt(pack_mode_flags(fTileMode, fGradFlags));
- if (fColorCount > 2) {
- Rec* recs = fRecs;
- for (int i = 1; i < fColorCount; i++) {
- buffer.writeInt(recs[i].fPos);
- buffer.writeUInt(recs[i].fScale);
+ Descriptor desc;
+ desc.fColors = fOrigColors;
+ desc.fPos = fOrigPos;
+ desc.fCount = fColorCount;
+ desc.fTileMode = fTileMode;
+ desc.fGradFlags = fGradFlags;
+
+ const SkMatrix& m = this->getLocalMatrix();
+ desc.fLocalMatrix = m.isIdentity() ? NULL : &m;
+ desc.flatten(buffer);
+}
+
+SkGradientShaderBase::GpuColorType SkGradientShaderBase::getGpuColorType(SkColor colors[3]) const {
+ if (fColorCount <= 3) {
+ memcpy(colors, fOrigColors, fColorCount * sizeof(SkColor));
+ }
+
+ if (SkShader::kClamp_TileMode == fTileMode) {
+ if (2 == fColorCount) {
+ return kTwo_GpuColorType;
+ } else if (3 == fColorCount &&
+ (SkScalarAbs(
+ SkFixedToScalar(fRecs[1].fPos) - SK_ScalarHalf) < SK_Scalar1 / 1000)) {
+ return kThree_GpuColorType;
}
}
- buffer.writeMatrix(fPtsToUnit);
+ return kTexture_GpuColorType;
+}
+
+void SkGradientShaderBase::FlipGradientColors(SkColor* colorDst, Rec* recDst,
+ SkColor* colorSrc, Rec* recSrc,
+ int count) {
+ SkAutoSTArray<8, SkColor> colorsTemp(count);
+ for (int i = 0; i < count; ++i) {
+ int offset = count - i - 1;
+ colorsTemp[i] = colorSrc[offset];
+ }
+ if (count > 2) {
+ SkAutoSTArray<8, Rec> recsTemp(count);
+ for (int i = 0; i < count; ++i) {
+ int offset = count - i - 1;
+ recsTemp[i].fPos = SK_Fixed1 - recSrc[offset].fPos;
+ recsTemp[i].fScale = recSrc[offset].fScale;
+ }
+ memcpy(recDst, recsTemp.get(), count * sizeof(Rec));
+ }
+ memcpy(colorDst, colorsTemp.get(), count * sizeof(SkColor));
+}
+
+void SkGradientShaderBase::flipGradientColors() {
+ FlipGradientColors(fOrigColors, fRecs, fOrigColors, fRecs, fColorCount);
}
bool SkGradientShaderBase::isOpaque() const {
return fColorsAreOpaque;
}
-bool SkGradientShaderBase::setContext(const SkBitmap& device,
- const SkPaint& paint,
- const SkMatrix& matrix) {
- if (!this->INHERITED::setContext(device, paint, matrix)) {
- return false;
+static unsigned rounded_divide(unsigned numer, unsigned denom) {
+ return (numer + (denom >> 1)) / denom;
+}
+
+bool SkGradientShaderBase::onAsLuminanceColor(SkColor* lum) const {
+ // we just compute an average color.
+ // possibly we could weight this based on the proportional width for each color
+ // assuming they are not evenly distributed in the fPos array.
+ int r = 0;
+ int g = 0;
+ int b = 0;
+ const int n = fColorCount;
+ for (int i = 0; i < n; ++i) {
+ SkColor c = fOrigColors[i];
+ r += SkColorGetR(c);
+ g += SkColorGetG(c);
+ b += SkColorGetB(c);
}
+ *lum = SkColorSetRGB(rounded_divide(r, n), rounded_divide(g, n), rounded_divide(b, n));
+ return true;
+}
+SkGradientShaderBase::GradientShaderBaseContext::GradientShaderBaseContext(
+ const SkGradientShaderBase& shader, const ContextRec& rec)
+ : INHERITED(shader, rec)
+ , fCache(shader.refCache(getPaintAlpha()))
+{
const SkMatrix& inverse = this->getTotalInverse();
- fDstToIndex.setConcat(fPtsToUnit, inverse);
+ fDstToIndex.setConcat(shader.fPtsToUnit, inverse);
+
fDstToIndexProc = fDstToIndex.getMapXYProc();
- fDstToIndexClass = (uint8_t)SkShader::ComputeMatrixClass(fDstToIndex);
+ fDstToIndexClass = (uint8_t)SkShader::Context::ComputeMatrixClass(fDstToIndex);
// now convert our colors in to PMColors
unsigned paintAlpha = this->getPaintAlpha();
fFlags = this->INHERITED::getFlags();
- if (fColorsAreOpaque && paintAlpha == 0xFF) {
+ if (shader.fColorsAreOpaque && paintAlpha == 0xFF) {
fFlags |= kOpaqueAlpha_Flag;
}
// we can do span16 as long as our individual colors are opaque,
// regardless of the paint's alpha
- if (fColorsAreOpaque) {
+ if (shader.fColorsAreOpaque) {
fFlags |= kHasSpan16_Flag;
}
+}
- this->setCacheAlpha(paintAlpha);
- return true;
+SkGradientShaderBase::GradientShaderCache::GradientShaderCache(
+ U8CPU alpha, const SkGradientShaderBase& shader)
+ : fCacheAlpha(alpha)
+ , fShader(shader)
+ , fCache16Inited(false)
+ , fCache32Inited(false)
+{
+ // Only initialize the cache in getCache16/32.
+ fCache16 = NULL;
+ fCache32 = NULL;
+ fCache16Storage = NULL;
+ fCache32PixelRef = NULL;
}
-void SkGradientShaderBase::setCacheAlpha(U8CPU alpha) const {
- // if the new alpha differs from the previous time we were called, inval our cache
- // this will trigger the cache to be rebuilt.
- // we don't care about the first time, since the cache ptrs will already be NULL
- if (fCacheAlpha != alpha) {
- fCache16 = NULL; // inval the cache
- fCache32 = NULL; // inval the cache
- fCacheAlpha = alpha; // record the new alpha
- // inform our subclasses
- if (fCache32PixelRef) {
- fCache32PixelRef->notifyPixelsChanged();
- }
- }
+SkGradientShaderBase::GradientShaderCache::~GradientShaderCache() {
+ sk_free(fCache16Storage);
+ SkSafeUnref(fCache32PixelRef);
}
#define Fixed_To_Dot8(x) (((x) + 0x80) >> 8)
build a 16bit table as long as the original colors are opaque, even if the
paint specifies a non-opaque alpha.
*/
-void SkGradientShaderBase::Build16bitCache(uint16_t cache[], SkColor c0, SkColor c1,
- int count) {
+void SkGradientShaderBase::GradientShaderCache::Build16bitCache(
+ uint16_t cache[], SkColor c0, SkColor c1, int count) {
SkASSERT(count > 1);
SkASSERT(SkColorGetA(c0) == 0xFF);
SkASSERT(SkColorGetA(c1) == 0xFF);
*/
typedef uint32_t SkUFixed;
-void SkGradientShaderBase::Build32bitCache(SkPMColor cache[], SkColor c0, SkColor c1,
- int count, U8CPU paintAlpha, uint32_t gradFlags) {
+void SkGradientShaderBase::GradientShaderCache::Build32bitCache(
+ SkPMColor cache[], SkColor c0, SkColor c1,
+ int count, U8CPU paintAlpha, uint32_t gradFlags) {
SkASSERT(count > 1);
// need to apply paintAlpha to our two endpoints
return x - (x >> 16);
}
-static inline U16CPU bitsTo16(unsigned x, const unsigned bits) {
- SkASSERT(x < (1U << bits));
- if (6 == bits) {
- return (x << 10) | (x << 4) | (x >> 2);
- }
- if (8 == bits) {
- return (x << 8) | x;
- }
- sk_throw();
- return 0;
+const uint16_t* SkGradientShaderBase::GradientShaderCache::getCache16() {
+ SkOnce(&fCache16Inited, &fCache16Mutex, SkGradientShaderBase::GradientShaderCache::initCache16,
+ this);
+ SkASSERT(fCache16);
+ return fCache16;
}
-const uint16_t* SkGradientShaderBase::getCache16() const {
- if (fCache16 == NULL) {
- // double the count for dither entries
- const int entryCount = kCache16Count * 2;
- const size_t allocSize = sizeof(uint16_t) * entryCount;
-
- if (fCache16Storage == NULL) { // set the storage and our working ptr
- fCache16Storage = (uint16_t*)sk_malloc_throw(allocSize);
- }
- fCache16 = fCache16Storage;
- if (fColorCount == 2) {
- Build16bitCache(fCache16, fOrigColors[0], fOrigColors[1],
- kCache16Count);
- } else {
- Rec* rec = fRecs;
- int prevIndex = 0;
- for (int i = 1; i < fColorCount; i++) {
- int nextIndex = SkFixedToFFFF(rec[i].fPos) >> kCache16Shift;
- SkASSERT(nextIndex < kCache16Count);
-
- if (nextIndex > prevIndex)
- Build16bitCache(fCache16 + prevIndex, fOrigColors[i-1], fOrigColors[i], nextIndex - prevIndex + 1);
- prevIndex = nextIndex;
- }
- }
-
- if (fMapper) {
- fCache16Storage = (uint16_t*)sk_malloc_throw(allocSize);
- uint16_t* linear = fCache16; // just computed linear data
- uint16_t* mapped = fCache16Storage; // storage for mapped data
- SkUnitMapper* map = fMapper;
- for (int i = 0; i < kCache16Count; i++) {
- int index = map->mapUnit16(bitsTo16(i, kCache16Bits)) >> kCache16Shift;
- mapped[i] = linear[index];
- mapped[i + kCache16Count] = linear[index + kCache16Count];
- }
- sk_free(fCache16);
- fCache16 = fCache16Storage;
+void SkGradientShaderBase::GradientShaderCache::initCache16(GradientShaderCache* cache) {
+ // double the count for dither entries
+ const int entryCount = kCache16Count * 2;
+ const size_t allocSize = sizeof(uint16_t) * entryCount;
+
+ SkASSERT(NULL == cache->fCache16Storage);
+ cache->fCache16Storage = (uint16_t*)sk_malloc_throw(allocSize);
+ cache->fCache16 = cache->fCache16Storage;
+ if (cache->fShader.fColorCount == 2) {
+ Build16bitCache(cache->fCache16, cache->fShader.fOrigColors[0],
+ cache->fShader.fOrigColors[1], kCache16Count);
+ } else {
+ Rec* rec = cache->fShader.fRecs;
+ int prevIndex = 0;
+ for (int i = 1; i < cache->fShader.fColorCount; i++) {
+ int nextIndex = SkFixedToFFFF(rec[i].fPos) >> kCache16Shift;
+ SkASSERT(nextIndex < kCache16Count);
+
+ if (nextIndex > prevIndex)
+ Build16bitCache(cache->fCache16 + prevIndex, cache->fShader.fOrigColors[i-1],
+ cache->fShader.fOrigColors[i], nextIndex - prevIndex + 1);
+ prevIndex = nextIndex;
}
}
- return fCache16;
}
-const SkPMColor* SkGradientShaderBase::getCache32() const {
- if (fCache32 == NULL) {
- SkImageInfo info;
- info.fWidth = kCache32Count;
- info.fHeight = 4; // for our 4 dither rows
- info.fAlphaType = kPremul_SkAlphaType;
- info.fColorType = kPMColor_SkColorType;
+const SkPMColor* SkGradientShaderBase::GradientShaderCache::getCache32() {
+ SkOnce(&fCache32Inited, &fCache32Mutex, SkGradientShaderBase::GradientShaderCache::initCache32,
+ this);
+ SkASSERT(fCache32);
+ return fCache32;
+}
- if (NULL == fCache32PixelRef) {
- fCache32PixelRef = SkMallocPixelRef::NewAllocate(info, 0, NULL);
- }
- fCache32 = (SkPMColor*)fCache32PixelRef->getAddr();
- if (fColorCount == 2) {
- Build32bitCache(fCache32, fOrigColors[0], fOrigColors[1],
- kCache32Count, fCacheAlpha, fGradFlags);
- } else {
- Rec* rec = fRecs;
- int prevIndex = 0;
- for (int i = 1; i < fColorCount; i++) {
- int nextIndex = SkFixedToFFFF(rec[i].fPos) >> kCache32Shift;
- SkASSERT(nextIndex < kCache32Count);
-
- if (nextIndex > prevIndex)
- Build32bitCache(fCache32 + prevIndex, fOrigColors[i-1],
- fOrigColors[i], nextIndex - prevIndex + 1,
- fCacheAlpha, fGradFlags);
- prevIndex = nextIndex;
- }
+void SkGradientShaderBase::GradientShaderCache::initCache32(GradientShaderCache* cache) {
+ const int kNumberOfDitherRows = 4;
+ const SkImageInfo info = SkImageInfo::MakeN32Premul(kCache32Count, kNumberOfDitherRows);
+
+ SkASSERT(NULL == cache->fCache32PixelRef);
+ cache->fCache32PixelRef = SkMallocPixelRef::NewAllocate(info, 0, NULL);
+ cache->fCache32 = (SkPMColor*)cache->fCache32PixelRef->getAddr();
+ if (cache->fShader.fColorCount == 2) {
+ Build32bitCache(cache->fCache32, cache->fShader.fOrigColors[0],
+ cache->fShader.fOrigColors[1], kCache32Count, cache->fCacheAlpha,
+ cache->fShader.fGradFlags);
+ } else {
+ Rec* rec = cache->fShader.fRecs;
+ int prevIndex = 0;
+ for (int i = 1; i < cache->fShader.fColorCount; i++) {
+ int nextIndex = SkFixedToFFFF(rec[i].fPos) >> kCache32Shift;
+ SkASSERT(nextIndex < kCache32Count);
+
+ if (nextIndex > prevIndex)
+ Build32bitCache(cache->fCache32 + prevIndex, cache->fShader.fOrigColors[i-1],
+ cache->fShader.fOrigColors[i], nextIndex - prevIndex + 1,
+ cache->fCacheAlpha, cache->fShader.fGradFlags);
+ prevIndex = nextIndex;
}
+ }
+}
- if (fMapper) {
- SkMallocPixelRef* newPR = SkMallocPixelRef::NewAllocate(info, 0, NULL);
- SkPMColor* linear = fCache32; // just computed linear data
- SkPMColor* mapped = (SkPMColor*)newPR->getAddr(); // storage for mapped data
- SkUnitMapper* map = fMapper;
- for (int i = 0; i < kCache32Count; i++) {
- int index = map->mapUnit16((i << 8) | i) >> 8;
- mapped[i + kCache32Count*0] = linear[index + kCache32Count*0];
- mapped[i + kCache32Count*1] = linear[index + kCache32Count*1];
- mapped[i + kCache32Count*2] = linear[index + kCache32Count*2];
- mapped[i + kCache32Count*3] = linear[index + kCache32Count*3];
- }
- fCache32PixelRef->unref();
- fCache32PixelRef = newPR;
- fCache32 = (SkPMColor*)newPR->getAddr();
- }
+/*
+ * The gradient holds a cache for the most recent value of alpha. Successive
+ * callers with the same alpha value will share the same cache.
+ */
+SkGradientShaderBase::GradientShaderCache* SkGradientShaderBase::refCache(U8CPU alpha) const {
+ SkAutoMutexAcquire ama(fCacheMutex);
+ if (!fCache || fCache->getAlpha() != alpha) {
+ fCache.reset(SkNEW_ARGS(GradientShaderCache, (alpha, *this)));
}
- return fCache32;
+ // Increment the ref counter inside the mutex to ensure the returned pointer is still valid.
+ // Otherwise, the pointer may have been overwritten on a different thread before the object's
+ // ref count was incremented.
+ fCache.get()->ref();
+ return fCache;
}
+SK_DECLARE_STATIC_MUTEX(gGradientCacheMutex);
/*
* Because our caller might rebuild the same (logically the same) gradient
* over and over, we'd like to return exactly the same "bitmap" if possible,
void SkGradientShaderBase::getGradientTableBitmap(SkBitmap* bitmap) const {
// our caller assumes no external alpha, so we ensure that our cache is
// built with 0xFF
- this->setCacheAlpha(0xFF);
-
- // don't have a way to put the mapper into our cache-key yet
- if (fMapper) {
- // force our cahce32pixelref to be built
- (void)this->getCache32();
- bitmap->setConfig(SkImageInfo::MakeN32Premul(kCache32Count, 1));
- bitmap->setPixelRef(fCache32PixelRef);
- return;
- }
+ SkAutoTUnref<GradientShaderCache> cache(this->refCache(0xFF));
// build our key: [numColors + colors[] + {positions[]} + flags ]
int count = 1 + fColorCount + 1;
///////////////////////////////////
- SK_DECLARE_STATIC_MUTEX(gMutex);
- static SkBitmapCache* gCache;
+ static SkGradientBitmapCache* gCache;
// each cache cost 1K of RAM, since each bitmap will be 1x256 at 32bpp
static const int MAX_NUM_CACHED_GRADIENT_BITMAPS = 32;
- SkAutoMutexAcquire ama(gMutex);
+ SkAutoMutexAcquire ama(gGradientCacheMutex);
if (NULL == gCache) {
- gCache = SkNEW_ARGS(SkBitmapCache, (MAX_NUM_CACHED_GRADIENT_BITMAPS));
+ gCache = SkNEW_ARGS(SkGradientBitmapCache, (MAX_NUM_CACHED_GRADIENT_BITMAPS));
}
size_t size = count * sizeof(int32_t);
if (!gCache->find(storage.get(), size, bitmap)) {
// force our cahce32pixelref to be built
- (void)this->getCache32();
- bitmap->setConfig(SkImageInfo::MakeN32Premul(kCache32Count, 1));
- bitmap->setPixelRef(fCache32PixelRef);
+ (void)cache->getCache32();
+ bitmap->setInfo(SkImageInfo::MakeN32Premul(kCache32Count, 1));
+ bitmap->setPixelRef(cache->getCache32PixelRef());
gCache->add(storage.get(), size, *bitmap);
}
}
-void SkGradientShaderBase::commonAsAGradient(GradientInfo* info) const {
+void SkGradientShaderBase::commonAsAGradient(GradientInfo* info, bool flipGrad) const {
if (info) {
if (info->fColorCount >= fColorCount) {
+ SkColor* colorLoc;
+ Rec* recLoc;
+ if (flipGrad && (info->fColors || info->fColorOffsets)) {
+ SkAutoSTArray<8, SkColor> colorStorage(fColorCount);
+ SkAutoSTArray<8, Rec> recStorage(fColorCount);
+ colorLoc = colorStorage.get();
+ recLoc = recStorage.get();
+ FlipGradientColors(colorLoc, recLoc, fOrigColors, fRecs, fColorCount);
+ } else {
+ colorLoc = fOrigColors;
+ recLoc = fRecs;
+ }
if (info->fColors) {
- memcpy(info->fColors, fOrigColors, fColorCount * sizeof(SkColor));
+ memcpy(info->fColors, colorLoc, fColorCount * sizeof(SkColor));
}
if (info->fColorOffsets) {
if (fColorCount == 2) {
info->fColorOffsets[1] = SK_Scalar1;
} else if (fColorCount > 2) {
for (int i = 0; i < fColorCount; ++i) {
- info->fColorOffsets[i] = SkFixedToScalar(fRecs[i].fPos);
+ info->fColorOffsets[i] = SkFixedToScalar(recLoc[i].fPos);
}
}
}
str->append(" ");
str->append(gTileModeName[fTileMode]);
- // TODO: add "fMapper->toString(str);" when SkUnitMapper::toString is added
-
this->INHERITED::toString(str);
}
#endif
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
-#include "SkEmptyShader.h"
-
// assumes colors is SkColor* and pos is SkScalar*
#define EXPAND_1_COLOR(count) \
SkColor tmp[2]; \
} while (0)
static void desc_init(SkGradientShaderBase::Descriptor* desc,
- const SkColor colors[],
- const SkScalar pos[], int colorCount,
- SkShader::TileMode mode,
- SkUnitMapper* mapper, uint32_t flags) {
- desc->fColors = colors;
- desc->fPos = pos;
- desc->fCount = colorCount;
- desc->fTileMode = mode;
- desc->fMapper = mapper;
- desc->fFlags = flags;
+ const SkColor colors[], const SkScalar pos[], int colorCount,
+ SkShader::TileMode mode, uint32_t flags, const SkMatrix* localMatrix) {
+ desc->fColors = colors;
+ desc->fPos = pos;
+ desc->fCount = colorCount;
+ desc->fTileMode = mode;
+ desc->fGradFlags = flags;
+ desc->fLocalMatrix = localMatrix;
}
SkShader* SkGradientShader::CreateLinear(const SkPoint pts[2],
const SkColor colors[],
const SkScalar pos[], int colorCount,
SkShader::TileMode mode,
- SkUnitMapper* mapper,
- uint32_t flags) {
+ uint32_t flags,
+ const SkMatrix* localMatrix) {
if (NULL == pts || NULL == colors || colorCount < 1) {
return NULL;
}
EXPAND_1_COLOR(colorCount);
SkGradientShaderBase::Descriptor desc;
- desc_init(&desc, colors, pos, colorCount, mode, mapper, flags);
+ desc_init(&desc, colors, pos, colorCount, mode, flags, localMatrix);
return SkNEW_ARGS(SkLinearGradient, (pts, desc));
}
const SkColor colors[],
const SkScalar pos[], int colorCount,
SkShader::TileMode mode,
- SkUnitMapper* mapper,
- uint32_t flags) {
+ uint32_t flags,
+ const SkMatrix* localMatrix) {
if (radius <= 0 || NULL == colors || colorCount < 1) {
return NULL;
}
EXPAND_1_COLOR(colorCount);
SkGradientShaderBase::Descriptor desc;
- desc_init(&desc, colors, pos, colorCount, mode, mapper, flags);
+ desc_init(&desc, colors, pos, colorCount, mode, flags, localMatrix);
return SkNEW_ARGS(SkRadialGradient, (center, radius, desc));
}
const SkScalar pos[],
int colorCount,
SkShader::TileMode mode,
- SkUnitMapper* mapper,
- uint32_t flags) {
+ uint32_t flags,
+ const SkMatrix* localMatrix) {
if (startRadius < 0 || endRadius < 0 || NULL == colors || colorCount < 1) {
return NULL;
}
EXPAND_1_COLOR(colorCount);
SkGradientShaderBase::Descriptor desc;
- desc_init(&desc, colors, pos, colorCount, mode, mapper, flags);
+ desc_init(&desc, colors, pos, colorCount, mode, flags, localMatrix);
return SkNEW_ARGS(SkTwoPointRadialGradient,
(start, startRadius, end, endRadius, desc));
}
const SkScalar pos[],
int colorCount,
SkShader::TileMode mode,
- SkUnitMapper* mapper,
- uint32_t flags) {
+ uint32_t flags,
+ const SkMatrix* localMatrix) {
if (startRadius < 0 || endRadius < 0 || NULL == colors || colorCount < 1) {
return NULL;
}
if (start == end && startRadius == endRadius) {
- return SkNEW(SkEmptyShader);
+ return SkShader::CreateEmptyShader();
}
+
EXPAND_1_COLOR(colorCount);
+ bool flipGradient = startRadius > endRadius;
+
SkGradientShaderBase::Descriptor desc;
- desc_init(&desc, colors, pos, colorCount, mode, mapper, flags);
- return SkNEW_ARGS(SkTwoPointConicalGradient,
- (start, startRadius, end, endRadius, desc));
+
+ if (!flipGradient) {
+ desc_init(&desc, colors, pos, colorCount, mode, flags, localMatrix);
+ return SkNEW_ARGS(SkTwoPointConicalGradient,
+ (start, startRadius, end, endRadius, flipGradient, desc));
+ } else {
+ SkAutoSTArray<8, SkColor> colorsNew(colorCount);
+ SkAutoSTArray<8, SkScalar> posNew(colorCount);
+ for (int i = 0; i < colorCount; ++i) {
+ colorsNew[i] = colors[colorCount - i - 1];
+ }
+
+ if (pos) {
+ for (int i = 0; i < colorCount; ++i) {
+ posNew[i] = 1 - pos[colorCount - i - 1];
+ }
+ desc_init(&desc, colorsNew.get(), posNew.get(), colorCount, mode, flags, localMatrix);
+ } else {
+ desc_init(&desc, colorsNew.get(), NULL, colorCount, mode, flags, localMatrix);
+ }
+
+ return SkNEW_ARGS(SkTwoPointConicalGradient,
+ (end, endRadius, start, startRadius, flipGradient, desc));
+ }
}
SkShader* SkGradientShader::CreateSweep(SkScalar cx, SkScalar cy,
const SkColor colors[],
const SkScalar pos[],
- int colorCount, SkUnitMapper* mapper,
- uint32_t flags) {
+ int colorCount,
+ uint32_t flags,
+ const SkMatrix* localMatrix) {
if (NULL == colors || colorCount < 1) {
return NULL;
}
EXPAND_1_COLOR(colorCount);
SkGradientShaderBase::Descriptor desc;
- desc_init(&desc, colors, pos, colorCount, SkShader::kClamp_TileMode, mapper, flags);
+ desc_init(&desc, colors, pos, colorCount, SkShader::kClamp_TileMode, flags, localMatrix);
return SkNEW_ARGS(SkSweepGradient, (cx, cy, desc));
}
#if SK_SUPPORT_GPU
#include "effects/GrTextureStripAtlas.h"
-#include "GrTBackendEffectFactory.h"
+#include "GrTBackendProcessorFactory.h"
+#include "gl/builders/GrGLProgramBuilder.h"
#include "SkGr.h"
-GrGLGradientEffect::GrGLGradientEffect(const GrBackendEffectFactory& factory)
+GrGLGradientEffect::GrGLGradientEffect(const GrBackendProcessorFactory& factory)
: INHERITED(factory)
, fCachedYCoord(SK_ScalarMax) {
}
GrGLGradientEffect::~GrGLGradientEffect() { }
-void GrGLGradientEffect::emitUniforms(GrGLShaderBuilder* builder, EffectKey key) {
+void GrGLGradientEffect::emitUniforms(GrGLFPBuilder* builder, uint32_t baseKey) {
- if (GrGradientEffect::kTwo_ColorType == ColorTypeFromKey(key)) { // 2 Color case
- fColorStartUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+ if (SkGradientShaderBase::kTwo_GpuColorType == ColorTypeFromKey(baseKey)) { // 2 Color case
+ fColorStartUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
kVec4f_GrSLType, "GradientStartColor");
- fColorEndUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+ fColorEndUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
kVec4f_GrSLType, "GradientEndColor");
- } else if (GrGradientEffect::kThree_ColorType == ColorTypeFromKey(key)){ // 3 Color Case
- fColorStartUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+ } else if (SkGradientShaderBase::kThree_GpuColorType == ColorTypeFromKey(baseKey)){ // 3 Color Case
+ fColorStartUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
kVec4f_GrSLType, "GradientStartColor");
- fColorMidUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+ fColorMidUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
kVec4f_GrSLType, "GradientMidColor");
- fColorEndUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+ fColorEndUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
kVec4f_GrSLType, "GradientEndColor");
} else { // if not a fast case
- fFSYUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+ fFSYUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
kFloat_GrSLType, "GradientYCoordFS");
}
}
-static inline void set_color_uni(const GrGLUniformManager& uman,
- const GrGLUniformManager::UniformHandle uni,
+static inline void set_color_uni(const GrGLProgramDataManager& pdman,
+ const GrGLProgramDataManager::UniformHandle uni,
const SkColor* color) {
- uman.set4f(uni,
- SkColorGetR(*color) / 255.f,
- SkColorGetG(*color) / 255.f,
- SkColorGetB(*color) / 255.f,
- SkColorGetA(*color) / 255.f);
+ pdman.set4f(uni,
+ SkColorGetR(*color) / 255.f,
+ SkColorGetG(*color) / 255.f,
+ SkColorGetB(*color) / 255.f,
+ SkColorGetA(*color) / 255.f);
}
-static inline void set_mul_color_uni(const GrGLUniformManager& uman,
- const GrGLUniformManager::UniformHandle uni,
+static inline void set_mul_color_uni(const GrGLProgramDataManager& pdman,
+ const GrGLProgramDataManager::UniformHandle uni,
const SkColor* color){
float a = SkColorGetA(*color) / 255.f;
float aDiv255 = a / 255.f;
- uman.set4f(uni,
- SkColorGetR(*color) * aDiv255,
- SkColorGetG(*color) * aDiv255,
- SkColorGetB(*color) * aDiv255,
- a);
+ pdman.set4f(uni,
+ SkColorGetR(*color) * aDiv255,
+ SkColorGetG(*color) * aDiv255,
+ SkColorGetB(*color) * aDiv255,
+ a);
}
-void GrGLGradientEffect::setData(const GrGLUniformManager& uman,
- const GrDrawEffect& drawEffect) {
+void GrGLGradientEffect::setData(const GrGLProgramDataManager& pdman,
+ const GrProcessor& processor) {
- const GrGradientEffect& e = drawEffect.castEffect<GrGradientEffect>();
+ const GrGradientEffect& e = processor.cast<GrGradientEffect>();
- if (GrGradientEffect::kTwo_ColorType == e.getColorType()){
+ if (SkGradientShaderBase::kTwo_GpuColorType == e.getColorType()){
if (GrGradientEffect::kBeforeInterp_PremulType == e.getPremulType()) {
- set_mul_color_uni(uman, fColorStartUni, e.getColors(0));
- set_mul_color_uni(uman, fColorEndUni, e.getColors(1));
+ set_mul_color_uni(pdman, fColorStartUni, e.getColors(0));
+ set_mul_color_uni(pdman, fColorEndUni, e.getColors(1));
} else {
- set_color_uni(uman, fColorStartUni, e.getColors(0));
- set_color_uni(uman, fColorEndUni, e.getColors(1));
+ set_color_uni(pdman, fColorStartUni, e.getColors(0));
+ set_color_uni(pdman, fColorEndUni, e.getColors(1));
}
- } else if (GrGradientEffect::kThree_ColorType == e.getColorType()){
+ } else if (SkGradientShaderBase::kThree_GpuColorType == e.getColorType()){
if (GrGradientEffect::kBeforeInterp_PremulType == e.getPremulType()) {
- set_mul_color_uni(uman, fColorStartUni, e.getColors(0));
- set_mul_color_uni(uman, fColorMidUni, e.getColors(1));
- set_mul_color_uni(uman, fColorEndUni, e.getColors(2));
+ set_mul_color_uni(pdman, fColorStartUni, e.getColors(0));
+ set_mul_color_uni(pdman, fColorMidUni, e.getColors(1));
+ set_mul_color_uni(pdman, fColorEndUni, e.getColors(2));
} else {
- set_color_uni(uman, fColorStartUni, e.getColors(0));
- set_color_uni(uman, fColorMidUni, e.getColors(1));
- set_color_uni(uman, fColorEndUni, e.getColors(2));
+ set_color_uni(pdman, fColorStartUni, e.getColors(0));
+ set_color_uni(pdman, fColorMidUni, e.getColors(1));
+ set_color_uni(pdman, fColorEndUni, e.getColors(2));
}
} else {
SkScalar yCoord = e.getYCoord();
if (yCoord != fCachedYCoord) {
- uman.set1f(fFSYUni, yCoord);
+ pdman.set1f(fFSYUni, yCoord);
fCachedYCoord = yCoord;
}
}
}
-GrGLEffect::EffectKey GrGLGradientEffect::GenBaseGradientKey(const GrDrawEffect& drawEffect) {
- const GrGradientEffect& e = drawEffect.castEffect<GrGradientEffect>();
+uint32_t GrGLGradientEffect::GenBaseGradientKey(const GrProcessor& processor) {
+ const GrGradientEffect& e = processor.cast<GrGradientEffect>();
- EffectKey key = 0;
+ uint32_t key = 0;
- if (GrGradientEffect::kTwo_ColorType == e.getColorType()) {
+ if (SkGradientShaderBase::kTwo_GpuColorType == e.getColorType()) {
key |= kTwoColorKey;
- } else if (GrGradientEffect::kThree_ColorType == e.getColorType()){
+ } else if (SkGradientShaderBase::kThree_GpuColorType == e.getColorType()){
key |= kThreeColorKey;
}
return key;
}
-void GrGLGradientEffect::emitColor(GrGLShaderBuilder* builder,
+void GrGLGradientEffect::emitColor(GrGLFPBuilder* builder,
const char* gradientTValue,
- EffectKey key,
+ uint32_t baseKey,
const char* outputColor,
const char* inputColor,
const TextureSamplerArray& samplers) {
- if (GrGradientEffect::kTwo_ColorType == ColorTypeFromKey(key)){
- builder->fsCodeAppendf("\tvec4 colorTemp = mix(%s, %s, clamp(%s, 0.0, 1.0));\n",
+ GrGLFPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+ if (SkGradientShaderBase::kTwo_GpuColorType == ColorTypeFromKey(baseKey)){
+ fsBuilder->codeAppendf("\tvec4 colorTemp = mix(%s, %s, clamp(%s, 0.0, 1.0));\n",
builder->getUniformVariable(fColorStartUni).c_str(),
builder->getUniformVariable(fColorEndUni).c_str(),
gradientTValue);
// The gradient SkShader reporting opaque is more restrictive than necessary in the two pt
// case. Make sure the key reflects this optimization (and note that it can use the same
// shader as thekBeforeIterp case). This same optimization applies to the 3 color case below.
- if (GrGradientEffect::kAfterInterp_PremulType == PremulTypeFromKey(key)) {
- builder->fsCodeAppend("\tcolorTemp.rgb *= colorTemp.a;\n");
+ if (GrGradientEffect::kAfterInterp_PremulType == PremulTypeFromKey(baseKey)) {
+ fsBuilder->codeAppend("\tcolorTemp.rgb *= colorTemp.a;\n");
}
- builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
+ fsBuilder->codeAppendf("\t%s = %s;\n", outputColor,
(GrGLSLExpr4(inputColor) * GrGLSLExpr4("colorTemp")).c_str());
- } else if (GrGradientEffect::kThree_ColorType == ColorTypeFromKey(key)){
- builder->fsCodeAppendf("\tfloat oneMinus2t = 1.0 - (2.0 * (%s));\n",
+ } else if (SkGradientShaderBase::kThree_GpuColorType == ColorTypeFromKey(baseKey)){
+ fsBuilder->codeAppendf("\tfloat oneMinus2t = 1.0 - (2.0 * (%s));\n",
gradientTValue);
- builder->fsCodeAppendf("\tvec4 colorTemp = clamp(oneMinus2t, 0.0, 1.0) * %s;\n",
+ fsBuilder->codeAppendf("\tvec4 colorTemp = clamp(oneMinus2t, 0.0, 1.0) * %s;\n",
builder->getUniformVariable(fColorStartUni).c_str());
if (kTegra3_GrGLRenderer == builder->ctxInfo().renderer()) {
// The Tegra3 compiler will sometimes never return if we have
// min(abs(oneMinus2t), 1.0), or do the abs first in a separate expression.
- builder->fsCodeAppend("\tfloat minAbs = abs(oneMinus2t);\n");
- builder->fsCodeAppend("\tminAbs = minAbs > 1.0 ? 1.0 : minAbs;\n");
- builder->fsCodeAppendf("\tcolorTemp += (1.0 - minAbs) * %s;\n",
+ fsBuilder->codeAppend("\tfloat minAbs = abs(oneMinus2t);\n");
+ fsBuilder->codeAppend("\tminAbs = minAbs > 1.0 ? 1.0 : minAbs;\n");
+ fsBuilder->codeAppendf("\tcolorTemp += (1.0 - minAbs) * %s;\n",
builder->getUniformVariable(fColorMidUni).c_str());
} else {
- builder->fsCodeAppendf("\tcolorTemp += (1.0 - min(abs(oneMinus2t), 1.0)) * %s;\n",
+ fsBuilder->codeAppendf("\tcolorTemp += (1.0 - min(abs(oneMinus2t), 1.0)) * %s;\n",
builder->getUniformVariable(fColorMidUni).c_str());
}
- builder->fsCodeAppendf("\tcolorTemp += clamp(-oneMinus2t, 0.0, 1.0) * %s;\n",
+ fsBuilder->codeAppendf("\tcolorTemp += clamp(-oneMinus2t, 0.0, 1.0) * %s;\n",
builder->getUniformVariable(fColorEndUni).c_str());
- if (GrGradientEffect::kAfterInterp_PremulType == PremulTypeFromKey(key)) {
- builder->fsCodeAppend("\tcolorTemp.rgb *= colorTemp.a;\n");
+ if (GrGradientEffect::kAfterInterp_PremulType == PremulTypeFromKey(baseKey)) {
+ fsBuilder->codeAppend("\tcolorTemp.rgb *= colorTemp.a;\n");
}
- builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
+ fsBuilder->codeAppendf("\t%s = %s;\n", outputColor,
(GrGLSLExpr4(inputColor) * GrGLSLExpr4("colorTemp")).c_str());
} else {
- builder->fsCodeAppendf("\tvec2 coord = vec2(%s, %s);\n",
+ fsBuilder->codeAppendf("\tvec2 coord = vec2(%s, %s);\n",
gradientTValue,
builder->getUniformVariable(fFSYUni).c_str());
- builder->fsCodeAppendf("\t%s = ", outputColor);
- builder->fsAppendTextureLookupAndModulate(inputColor,
+ fsBuilder->codeAppendf("\t%s = ", outputColor);
+ fsBuilder->appendTextureLookupAndModulate(inputColor,
samplers[0],
"coord");
- builder->fsCodeAppend(";\n");
+ fsBuilder->codeAppend(";\n");
}
}
fIsOpaque = shader.isOpaque();
- SkShader::GradientInfo info;
- SkScalar pos[3] = {0};
-
- info.fColorCount = 3;
- info.fColors = &fColors[0];
- info.fColorOffsets = &pos[0];
- shader.asAGradient(&info);
+ fColorType = shader.getGpuColorType(&fColors[0]);
// The two and three color specializations do not currently support tiling.
- bool foundSpecialCase = false;
- if (SkShader::kClamp_TileMode == info.fTileMode) {
- if (2 == info.fColorCount) {
- fRow = -1; // flag for no atlas
- fColorType = kTwo_ColorType;
- foundSpecialCase = true;
- } else if (3 == info.fColorCount &&
- (SkScalarAbs(pos[1] - SK_ScalarHalf) < SK_Scalar1 / 1000)) { // 3 color symmetric
- fRow = -1; // flag for no atlas
- fColorType = kThree_ColorType;
- foundSpecialCase = true;
- }
- }
- if (foundSpecialCase) {
- if (SkGradientShader::kInterpolateColorsInPremul_Flag & info.fGradientFlags) {
+ if (SkGradientShaderBase::kTwo_GpuColorType == fColorType ||
+ SkGradientShaderBase::kThree_GpuColorType == fColorType) {
+ fRow = -1;
+
+ if (SkGradientShader::kInterpolateColorsInPremul_Flag & shader.getGradFlags()) {
fPremulType = kBeforeInterp_PremulType;
} else {
fPremulType = kAfterInterp_PremulType;
fPremulType = kBeforeInterp_PremulType;
SkBitmap bitmap;
shader.getGradientTableBitmap(&bitmap);
- fColorType = kTexture_ColorType;
GrTextureStripAtlas::Desc desc;
desc.fWidth = bitmap.width();
desc.fHeight = 32;
desc.fRowHeight = bitmap.height();
desc.fContext = ctx;
- desc.fConfig = SkImageInfo2GrPixelConfig(bitmap.colorType(), bitmap.alphaType());
+ desc.fConfig = SkImageInfo2GrPixelConfig(bitmap.info());
fAtlas = GrTextureStripAtlas::GetAtlas(desc);
- SkASSERT(NULL != fAtlas);
+ SkASSERT(fAtlas);
// We always filter the gradient table. Each table is one row of a texture, always y-clamp.
GrTextureParams params;
fRow = fAtlas->lockRow(bitmap);
if (-1 != fRow) {
- fYCoord = fAtlas->getYOffset(fRow) + SK_ScalarHalf *
- fAtlas->getVerticalScaleFactor();
+ fYCoord = fAtlas->getYOffset(fRow) + SK_ScalarHalf * fAtlas->getNormalizedTexelHeight();
fCoordTransform.reset(kCoordSet, matrix, fAtlas->getTexture());
fTextureAccess.reset(fAtlas->getTexture(), params);
} else {
- GrTexture* texture = GrLockAndRefCachedBitmapTexture(ctx, bitmap, ¶ms);
+ SkAutoTUnref<GrTexture> texture(GrRefCachedBitmapTexture(ctx, bitmap, ¶ms));
fCoordTransform.reset(kCoordSet, matrix, texture);
fTextureAccess.reset(texture, params);
fYCoord = SK_ScalarHalf;
-
- // Unlock immediately, this is not great, but we don't have a way of
- // knowing when else to unlock it currently, so it may get purged from
- // the cache, but it'll still be ref'd until it's no longer being used.
- GrUnlockAndUnrefCachedBitmapTexture(texture);
}
this->addTextureAccess(&fTextureAccess);
}
}
}
-bool GrGradientEffect::onIsEqual(const GrEffect& effect) const {
- const GrGradientEffect& s = CastEffect<GrGradientEffect>(effect);
+bool GrGradientEffect::onIsEqual(const GrFragmentProcessor& processor) const {
+ const GrGradientEffect& s = processor.cast<GrGradientEffect>();
if (this->fColorType == s.getColorType()){
- if (kTwo_ColorType == fColorType) {
+ if (SkGradientShaderBase::kTwo_GpuColorType == fColorType) {
if (*this->getColors(0) != *s.getColors(0) ||
*this->getColors(1) != *s.getColors(1)) {
return false;
}
- } else if (kThree_ColorType == fColorType) {
+ } else if (SkGradientShaderBase::kThree_GpuColorType == fColorType) {
if (*this->getColors(0) != *s.getColors(0) ||
*this->getColors(1) != *s.getColors(1) ||
*this->getColors(2) != *s.getColors(2)) {
}
}
- return fTextureAccess.getTexture() == s.fTextureAccess.getTexture() &&
- fTextureAccess.getParams().getTileModeX() ==
- s.fTextureAccess.getParams().getTileModeX() &&
- this->useAtlas() == s.useAtlas() &&
- fCoordTransform.getMatrix().cheapEqualTo(s.fCoordTransform.getMatrix());
+ SkASSERT(this->useAtlas() == s.useAtlas());
+ return true;
}
return false;
}
-void GrGradientEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const {
- if (fIsOpaque && (kA_GrColorComponentFlag & *validFlags) && 0xff == GrColorUnpackA(*color)) {
- *validFlags = kA_GrColorComponentFlag;
+void GrGradientEffect::onComputeInvariantOutput(InvariantOutput* inout) const {
+ if (fIsOpaque) {
+ inout->mulByUnknownOpaqueColor();
} else {
- *validFlags = 0;
+ inout->mulByUnknownColor();
}
}
SkScalar stop = 0.f;
for (int i = 0; i < outColors; ++i) {
colors[i] = random->nextU();
- if (NULL != *stops) {
+ if (*stops) {
(*stops)[i] = stop;
stop = i < outColors - 1 ? stop + random->nextUScalar1() * (1.f - stop) : 1.f;
}