summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Chromium Automerger <chromium-automerger@android>2013-12-16 13:12:17 +0000
committerAndroid Chromium Automerger <chromium-automerger@android>2013-12-16 13:12:17 +0000
commitf210270120ee1da24674ae29ce081a95ce9b36e3 (patch)
tree6d6891571b5b8503b79c3f2594be27787f72c965
parente69bc09ae4a12f72e1918c0cb1729da7aac1a79e (diff)
parentc2062d0e1bd6b258229669463ab5ce7020780c8a (diff)
downloadsrc-f210270120ee1da24674ae29ce081a95ce9b36e3.tar.gz
Merge third_party/skia/src from https://chromium.googlesource.com/external/skia/src.git at c2062d0e1bd6b258229669463ab5ce7020780c8a
This commit was generated by merge_from_chromium.py. Change-Id: I8ed55c7efa600f30df090e824e3770368eb28e72
-rw-r--r--core/SkBitmap.cpp32
-rw-r--r--core/SkBitmapProcState.cpp76
-rw-r--r--core/SkBitmapScaler.cpp2
-rw-r--r--core/SkImageFilterUtils.cpp16
-rw-r--r--core/SkMallocPixelRef.cpp123
-rw-r--r--core/SkMaskFilter.cpp8
-rw-r--r--core/SkPath.cpp97
-rw-r--r--core/SkPathRef.cpp157
-rw-r--r--core/SkPixelRef.cpp17
-rw-r--r--core/SkScaledImageCache.cpp49
-rw-r--r--core/SkScaledImageCache.h11
-rw-r--r--effects/SkDisplacementMapEffect.cpp16
-rw-r--r--effects/SkPictureImageFilter.cpp77
-rw-r--r--effects/gradients/SkGradientShader.cpp14
-rw-r--r--gpu/GrSurface.cpp10
-rw-r--r--gpu/SkGpuDevice.cpp28
-rw-r--r--gpu/SkGr.cpp30
-rw-r--r--gpu/SkGrPixelRef.cpp37
-rw-r--r--image/SkDataPixelRef.cpp5
-rw-r--r--image/SkDataPixelRef.h2
-rw-r--r--image/SkImage_Raster.cpp6
-rw-r--r--image/SkSurface_Raster.cpp16
-rw-r--r--images/SkImageRef.cpp19
-rw-r--r--images/SkImageRef_GlobalPool.cpp6
-rw-r--r--images/SkImageRef_ashmem.cpp12
-rw-r--r--images/SkImageRef_ashmem.h2
-rw-r--r--lazy/SkCachingPixelRef.cpp37
-rw-r--r--lazy/SkCachingPixelRef.h6
-rw-r--r--lazy/SkDiscardableMemoryPool.cpp6
-rw-r--r--lazy/SkDiscardablePixelRef.cpp40
-rw-r--r--lazy/SkDiscardablePixelRef.h6
31 files changed, 689 insertions, 274 deletions
diff --git a/core/SkBitmap.cpp b/core/SkBitmap.cpp
index 25a6b1db..b387795e 100644
--- a/core/SkBitmap.cpp
+++ b/core/SkBitmap.cpp
@@ -298,7 +298,7 @@ bool SkBitmap::setConfig(Config config, int width, int height, size_t rowBytes,
}
if (rowBytes == 0) {
rowBytes = SkBitmap::ComputeRowBytes(config, width);
- if (0 == rowBytes && kNo_Config != config) {
+ if (0 == rowBytes && kNo_Config != config && width > 0) {
goto BAD_CONFIG;
}
}
@@ -453,10 +453,20 @@ void SkBitmap::setPixels(void* p, SkColorTable* ctable) {
return;
}
- Sk64 size = this->getSize64();
- SkASSERT(!size.isNeg() && size.is32());
+ SkImageInfo info;
+ if (!this->asImageInfo(&info)) {
+ this->setPixelRef(NULL, 0);
+ return;
+ }
+
+ SkPixelRef* pr = SkMallocPixelRef::NewDirect(info, p, fRowBytes, ctable);
+ if (NULL == pr) {
+ this->setPixelRef(NULL, 0);
+ return;
+ }
+
+ this->setPixelRef(pr)->unref();
- this->setPixelRef(new SkMallocPixelRef(p, size.get32(), ctable, false))->unref();
// since we're already allocated, we lockPixels right away
this->lockPixels();
SkDEBUGCODE(this->validate();)
@@ -521,17 +531,19 @@ GrTexture* SkBitmap::getTexture() const {
*/
bool SkBitmap::HeapAllocator::allocPixelRef(SkBitmap* dst,
SkColorTable* ctable) {
- Sk64 size = dst->getSize64();
- if (size.isNeg() || !size.is32()) {
+ SkImageInfo info;
+ if (!dst->asImageInfo(&info)) {
+// SkDebugf("unsupported config for info %d\n", dst->config());
return false;
}
-
- void* addr = sk_malloc_flags(size.get32(), 0); // returns NULL on failure
- if (NULL == addr) {
+
+ SkPixelRef* pr = SkMallocPixelRef::NewAllocate(info, dst->rowBytes(),
+ ctable);
+ if (NULL == pr) {
return false;
}
- dst->setPixelRef(new SkMallocPixelRef(addr, size.get32(), ctable))->unref();
+ dst->setPixelRef(pr, 0)->unref();
// since we're already allocated, we lockPixels right away
dst->lockPixels();
return true;
diff --git a/core/SkBitmapProcState.cpp b/core/SkBitmapProcState.cpp
index 39f6a780..cdc582bf 100644
--- a/core/SkBitmapProcState.cpp
+++ b/core/SkBitmapProcState.cpp
@@ -106,11 +106,33 @@ static SkScalar effective_matrix_scale_sqrd(const SkMatrix& mat) {
return SkMaxScalar(v1.lengthSqd(), v2.lengthSqd());
}
+class AutoScaledCacheUnlocker {
+public:
+ AutoScaledCacheUnlocker(SkScaledImageCache::ID** idPtr) : fIDPtr(idPtr) {}
+ ~AutoScaledCacheUnlocker() {
+ if (fIDPtr && *fIDPtr) {
+ SkScaledImageCache::Unlock(*fIDPtr);
+ *fIDPtr = NULL;
+ }
+ }
+
+ // forgets the ID, so it won't call Unlock
+ void release() {
+ fIDPtr = NULL;
+ }
+
+private:
+ SkScaledImageCache::ID** fIDPtr;
+};
+#define AutoScaledCacheUnlocker(...) SK_REQUIRE_LOCAL_VAR(AutoScaledCacheUnlocker)
+
// TODO -- we may want to pass the clip into this function so we only scale
// the portion of the image that we're going to need. This will complicate
// the interface to the cache, but might be well worth it.
bool SkBitmapProcState::possiblyScaleImage() {
+ AutoScaledCacheUnlocker unlocker(&fScaledCacheID);
+
SkASSERT(NULL == fBitmap);
SkASSERT(NULL == fScaledCacheID);
@@ -132,6 +154,17 @@ bool SkBitmapProcState::possiblyScaleImage() {
fScaledCacheID = SkScaledImageCache::FindAndLock(fOrigBitmap,
invScaleX, invScaleY,
&fScaledBitmap);
+ if (fScaledCacheID) {
+ fScaledBitmap.lockPixels();
+ if (!fScaledBitmap.getPixels()) {
+ fScaledBitmap.unlockPixels();
+ // found a purged entry (discardablememory?), release it
+ SkScaledImageCache::Unlock(fScaledCacheID);
+ fScaledCacheID = NULL;
+ // fall through to rebuild
+ }
+ }
+
if (NULL == fScaledCacheID) {
int dest_width = SkScalarCeilToInt(fOrigBitmap.width() / invScaleX);
int dest_height = SkScalarCeilToInt(fOrigBitmap.height() / invScaleY);
@@ -154,18 +187,19 @@ bool SkBitmapProcState::possiblyScaleImage() {
return false;
}
+ SkASSERT(NULL != fScaledBitmap.getPixels());
fScaledCacheID = SkScaledImageCache::AddAndLock(fOrigBitmap,
invScaleX,
invScaleY,
fScaledBitmap);
- }
- fScaledBitmap.lockPixels(); // wonder if Resize() should have locked this
- if (!fScaledBitmap.getPixels()) {
- // TODO: find out how this can happen, and add a unittest to exercise
- // inspired by BUG=chromium:295895
- return false;
+ if (!fScaledCacheID) {
+ fScaledBitmap.reset();
+ return false;
+ }
+ SkASSERT(NULL != fScaledBitmap.getPixels());
}
+ SkASSERT(NULL != fScaledBitmap.getPixels());
fBitmap = &fScaledBitmap;
// set the inv matrix type to translate-only;
@@ -174,6 +208,7 @@ bool SkBitmapProcState::possiblyScaleImage() {
// no need for any further filtering; we just did it!
fFilterLevel = SkPaint::kNone_FilterLevel;
+ unlocker.release();
return true;
}
@@ -248,6 +283,7 @@ bool SkBitmapProcState::possiblyScaleImage() {
fScaledBitmap.setPixels(level.fPixels);
fBitmap = &fScaledBitmap;
fFilterLevel = SkPaint::kLow_FilterLevel;
+ unlocker.release();
return true;
}
}
@@ -273,15 +309,34 @@ static bool get_locked_pixels(const SkBitmap& src, int pow2, SkBitmap* dst) {
}
bool SkBitmapProcState::lockBaseBitmap() {
+ AutoScaledCacheUnlocker unlocker(&fScaledCacheID);
+
SkPixelRef* pr = fOrigBitmap.pixelRef();
+ SkASSERT(NULL == fScaledCacheID);
+
if (pr->isLocked() || !pr->implementsDecodeInto()) {
// fast-case, no need to look in our cache
fScaledBitmap = fOrigBitmap;
+ fScaledBitmap.lockPixels();
+ if (NULL == fScaledBitmap.getPixels()) {
+ return false;
+ }
} else {
fScaledCacheID = SkScaledImageCache::FindAndLock(fOrigBitmap,
SK_Scalar1, SK_Scalar1,
&fScaledBitmap);
+ if (fScaledCacheID) {
+ fScaledBitmap.lockPixels();
+ if (!fScaledBitmap.getPixels()) {
+ fScaledBitmap.unlockPixels();
+ // found a purged entry (discardablememory?), release it
+ SkScaledImageCache::Unlock(fScaledCacheID);
+ fScaledCacheID = NULL;
+ // fall through to rebuild
+ }
+ }
+
if (NULL == fScaledCacheID) {
if (!get_locked_pixels(fOrigBitmap, 0, &fScaledBitmap)) {
return false;
@@ -299,13 +354,8 @@ bool SkBitmapProcState::lockBaseBitmap() {
}
}
}
- fScaledBitmap.lockPixels(); // just 'cause the cache made a copy :(
- if (!fScaledBitmap.getPixels()) {
- // TODO: find out how this can happen, and add a unittest to exercise
- // inspired by BUG=chromium:295895
- return false;
- }
fBitmap = &fScaledBitmap;
+ unlocker.release();
return true;
}
@@ -334,6 +384,8 @@ bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) {
fInvMatrix = inv;
fFilterLevel = paint.getFilterLevel();
+ SkASSERT(NULL == fScaledCacheID);
+
// possiblyScaleImage will look to see if it can rescale the image as a
// preprocess; either by scaling up to the target size, or by selecting
// a nearby mipmap level. If it does, it will adjust the working
diff --git a/core/SkBitmapScaler.cpp b/core/SkBitmapScaler.cpp
index c28d4779..67a9508e 100644
--- a/core/SkBitmapScaler.cpp
+++ b/core/SkBitmapScaler.cpp
@@ -301,6 +301,8 @@ bool SkBitmapScaler::Resize(SkBitmap* resultPtr,
convolveProcs, true);
*resultPtr = result;
+ resultPtr->lockPixels();
+ SkASSERT(NULL != resultPtr->getPixels());
return true;
}
diff --git a/core/SkImageFilterUtils.cpp b/core/SkImageFilterUtils.cpp
index 8385fb44..a59cf7bb 100644
--- a/core/SkImageFilterUtils.cpp
+++ b/core/SkImageFilterUtils.cpp
@@ -15,8 +15,14 @@
#include "SkGr.h"
bool SkImageFilterUtils::WrapTexture(GrTexture* texture, int width, int height, SkBitmap* result) {
- result->setConfig(SkBitmap::kARGB_8888_Config, width, height);
- result->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (texture)))->unref();
+ SkImageInfo info = {
+ width,
+ height,
+ kPMColor_SkColorType,
+ kPremul_SkAlphaType,
+ };
+ result->setConfig(info);
+ result->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, texture)))->unref();
return true;
}
@@ -36,8 +42,12 @@ bool SkImageFilterUtils::GetInputResultGPU(SkImageFilter* filter, SkImageFilter:
} else {
if (filter->filterImage(proxy, src, ctm, result, offset)) {
if (!result->getTexture()) {
+ SkImageInfo info;
+ if (!result->asImageInfo(&info)) {
+ return false;
+ }
GrTexture* resultTex = GrLockAndRefCachedBitmapTexture(context, *result, NULL);
- result->setPixelRef(new SkGrPixelRef(resultTex))->unref();
+ result->setPixelRef(new SkGrPixelRef(info, resultTex))->unref();
GrUnlockAndUnrefCachedBitmapTexture(resultTex);
}
return true;
diff --git a/core/SkMallocPixelRef.cpp b/core/SkMallocPixelRef.cpp
index f229e9de..25337e7b 100644
--- a/core/SkMallocPixelRef.cpp
+++ b/core/SkMallocPixelRef.cpp
@@ -1,26 +1,104 @@
-
/*
* Copyright 2011 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
+
#include "SkMallocPixelRef.h"
#include "SkBitmap.h"
#include "SkFlattenableBuffers.h"
-SkMallocPixelRef::SkMallocPixelRef(void* storage, size_t size,
- SkColorTable* ctable, bool ownPixels) {
- if (NULL == storage) {
- SkASSERT(ownPixels);
- storage = sk_malloc_throw(size);
+static bool is_valid(const SkImageInfo& info, SkColorTable* ctable) {
+ if (info.fWidth < 0 ||
+ info.fHeight < 0 ||
+ (unsigned)info.fColorType > (unsigned)kLastEnum_SkColorType ||
+ (unsigned)info.fAlphaType > (unsigned)kLastEnum_SkAlphaType)
+ {
+ return false;
+ }
+
+ // these seem like good checks, but currently we have (at least) tests
+ // that expect the pixelref to succeed even when there is a mismatch
+ // with colortables. fix?
+#if 0
+ if (kIndex8_SkColorType == info.fColorType && NULL == ctable) {
+ return false;
+ }
+ if (kIndex8_SkColorType != info.fColorType && NULL != ctable) {
+ return false;
+ }
+#endif
+ return true;
+}
+
+SkMallocPixelRef* SkMallocPixelRef::NewDirect(const SkImageInfo& info,
+ void* addr,
+ size_t rowBytes,
+ SkColorTable* ctable) {
+ if (!is_valid(info, ctable)) {
+ return NULL;
+ }
+ return SkNEW_ARGS(SkMallocPixelRef, (info, addr, rowBytes, ctable, false));
+}
+
+SkMallocPixelRef* SkMallocPixelRef::NewAllocate(const SkImageInfo& info,
+ size_t requestedRowBytes,
+ SkColorTable* ctable) {
+ if (!is_valid(info, ctable)) {
+ return NULL;
+ }
+
+ int32_t minRB = info.minRowBytes();
+ if (minRB < 0) {
+ return NULL; // allocation will be too large
+ }
+ if (requestedRowBytes > 0 && (int32_t)requestedRowBytes < minRB) {
+ return NULL; // cannot meet requested rowbytes
+ }
+
+ int32_t rowBytes;
+ if (requestedRowBytes) {
+ rowBytes = requestedRowBytes;
+ } else {
+ rowBytes = minRB;
}
+
+ Sk64 bigSize;
+ bigSize.setMul(info.fHeight, rowBytes);
+ if (!bigSize.is32()) {
+ return NULL;
+ }
+
+ size_t size = bigSize.get32();
+ void* addr = sk_malloc_flags(size, 0);
+ if (NULL == addr) {
+ return NULL;
+ }
+
+ return SkNEW_ARGS(SkMallocPixelRef, (info, addr, rowBytes, ctable, true));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+SkMallocPixelRef::SkMallocPixelRef(const SkImageInfo& info, void* storage,
+ size_t rowBytes, SkColorTable* ctable,
+ bool ownsPixels)
+ : INHERITED(info)
+ , fOwnPixels(ownsPixels)
+{
+ SkASSERT(is_valid(info, ctable));
+ SkASSERT(rowBytes >= info.minRowBytes());
+
+ if (kIndex_8_SkColorType != info.fColorType) {
+ ctable = NULL;
+ }
+
fStorage = storage;
- fSize = size;
fCTable = ctable;
+ fRB = rowBytes;
SkSafeRef(ctable);
- fOwnPixels = ownPixels;
-
+
this->setPreLocked(fStorage, fCTable);
}
@@ -31,8 +109,8 @@ SkMallocPixelRef::~SkMallocPixelRef() {
}
}
-void* SkMallocPixelRef::onLockPixels(SkColorTable** ct) {
- *ct = fCTable;
+void* SkMallocPixelRef::onLockPixels(SkColorTable** ctable) {
+ *ctable = fCTable;
return fStorage;
}
@@ -40,10 +118,19 @@ void SkMallocPixelRef::onUnlockPixels() {
// nothing to do
}
+size_t SkMallocPixelRef::getAllocatedSizeInBytes() const {
+ return this->info().getSafeSize(fRB);
+}
+
void SkMallocPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
- buffer.writeByteArray(fStorage, fSize);
+ buffer.write32(fRB);
+
+ // TODO: replace this bulk write with a chunky one that can trim off any
+ // trailing bytes on each scanline (in case rowbytes > width*size)
+ size_t size = this->info().getSafeSize(fRB);
+ buffer.writeByteArray(fStorage, size);
buffer.writeBool(fCTable != NULL);
if (fCTable) {
fCTable->writeToBuffer(buffer);
@@ -51,16 +138,18 @@ void SkMallocPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const {
}
SkMallocPixelRef::SkMallocPixelRef(SkFlattenableReadBuffer& buffer)
- : INHERITED(buffer, NULL) {
- fSize = buffer.getArrayCount();
- fStorage = sk_malloc_throw(fSize);
- buffer.readByteArray(fStorage, fSize);
+ : INHERITED(buffer, NULL)
+ , fOwnPixels(true)
+{
+ fRB = buffer.read32();
+ size_t size = this->info().getSafeSize(fRB);
+ fStorage = sk_malloc_throw(size);
+ buffer.readByteArray(fStorage, size);
if (buffer.readBool()) {
fCTable = SkNEW_ARGS(SkColorTable, (buffer));
} else {
fCTable = NULL;
}
- fOwnPixels = true;
this->setPreLocked(fStorage, fCTable);
}
diff --git a/core/SkMaskFilter.cpp b/core/SkMaskFilter.cpp
index f062f135..1bc17bb4 100644
--- a/core/SkMaskFilter.cpp
+++ b/core/SkMaskFilter.cpp
@@ -349,10 +349,14 @@ bool SkMaskFilter::filterMaskGPU(GrContext* context,
if (!result) {
return false;
}
+ SkAutoUnref aur(dst);
+ SkImageInfo info;
resultBM->setConfig(srcBM.config(), dst->width(), dst->height());
- resultBM->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (dst)))->unref();
- dst->unref();
+ if (!resultBM->asImageInfo(&info)) {
+ return false;
+ }
+ resultBM->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, dst)))->unref();
return true;
}
diff --git a/core/SkPath.cpp b/core/SkPath.cpp
index eaa6c93d..af8b1aa5 100644
--- a/core/SkPath.cpp
+++ b/core/SkPath.cpp
@@ -15,11 +15,6 @@
#include "SkRRect.h"
#include "SkThread.h"
-// This value is just made-up for now. When count is 4, calling memset was much
-// slower than just writing the loop. This seems odd, and hopefully in the
-// future this we appear to have been a fluke...
-#define MIN_COUNT_FOR_MEMSET_TO_BE_FAST 16
-
////////////////////////////////////////////////////////////////////////////
/**
@@ -143,7 +138,6 @@ void SkPath::resetFields() {
//fPathRef is assumed to have been emptied by the caller.
fLastMoveToIndex = INITIAL_LASTMOVETOINDEX_VALUE;
fFillType = kWinding_FillType;
- fSegmentMask = 0;
fConvexity = kUnknown_Convexity;
fDirection = kUnknown_Direction;
@@ -182,7 +176,6 @@ void SkPath::copyFields(const SkPath& that) {
//fPathRef is assumed to have been set by the caller.
fLastMoveToIndex = that.fLastMoveToIndex;
fFillType = that.fFillType;
- fSegmentMask = that.fSegmentMask;
fConvexity = that.fConvexity;
fDirection = that.fDirection;
}
@@ -190,14 +183,8 @@ void SkPath::copyFields(const SkPath& that) {
bool operator==(const SkPath& a, const SkPath& b) {
// note: don't need to look at isConvex or bounds, since just comparing the
// raw data is sufficient.
-
- // We explicitly check fSegmentMask as a quick-reject. We could skip it,
- // since it is only a cache of info in the fVerbs, but its a fast way to
- // notice a difference
-
return &a == &b ||
- (a.fFillType == b.fFillType && a.fSegmentMask == b.fSegmentMask &&
- *a.fPathRef.get() == *b.fPathRef.get());
+ (a.fFillType == b.fFillType && *a.fPathRef.get() == *b.fPathRef.get());
}
void SkPath::swap(SkPath& that) {
@@ -207,7 +194,6 @@ void SkPath::swap(SkPath& that) {
fPathRef.swap(&that.fPathRef);
SkTSwap<int>(fLastMoveToIndex, that.fLastMoveToIndex);
SkTSwap<uint8_t>(fFillType, that.fFillType);
- SkTSwap<uint8_t>(fSegmentMask, that.fSegmentMask);
SkTSwap<uint8_t>(fConvexity, that.fConvexity);
SkTSwap<uint8_t>(fDirection, that.fDirection);
#ifdef SK_BUILD_FOR_ANDROID
@@ -674,7 +660,6 @@ void SkPath::lineTo(SkScalar x, SkScalar y) {
SkPathRef::Editor ed(&fPathRef);
ed.growForVerb(kLine_Verb)->set(x, y);
- fSegmentMask |= kLine_SegmentMask;
DIRTY_AFTER_EDIT;
}
@@ -695,7 +680,6 @@ void SkPath::quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) {
SkPoint* pts = ed.growForVerb(kQuad_Verb);
pts[0].set(x1, y1);
pts[1].set(x2, y2);
- fSegmentMask |= kQuad_SegmentMask;
DIRTY_AFTER_EDIT;
}
@@ -723,10 +707,9 @@ void SkPath::conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
this->injectMoveToIfNeeded();
SkPathRef::Editor ed(&fPathRef);
- SkPoint* pts = ed.growForConic(w);
+ SkPoint* pts = ed.growForVerb(kConic_Verb, w);
pts[0].set(x1, y1);
pts[1].set(x2, y2);
- fSegmentMask |= kConic_SegmentMask;
DIRTY_AFTER_EDIT;
}
@@ -751,7 +734,6 @@ void SkPath::cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
pts[0].set(x1, y1);
pts[1].set(x2, y2);
pts[2].set(x3, y3);
- fSegmentMask |= kCubic_SegmentMask;
DIRTY_AFTER_EDIT;
}
@@ -838,29 +820,19 @@ void SkPath::addPoly(const SkPoint pts[], int count, bool close) {
return;
}
- SkPathRef::Editor ed(&fPathRef);
- fLastMoveToIndex = ed.pathRef()->countPoints();
- uint8_t* vb;
- SkPoint* p;
+ fLastMoveToIndex = fPathRef->countPoints();
+
// +close makes room for the extra kClose_Verb
- ed.grow(count + close, count, &vb, &p);
+ SkPathRef::Editor ed(&fPathRef, count+close, count);
- memcpy(p, pts, count * sizeof(SkPoint));
- vb[~0] = kMove_Verb;
+ ed.growForVerb(kMove_Verb)->set(pts[0].fX, pts[0].fY);
if (count > 1) {
- // cast to unsigned, so if MIN_COUNT_FOR_MEMSET_TO_BE_FAST is defined to
- // be 0, the compiler will remove the test/branch entirely.
- if ((unsigned)count >= MIN_COUNT_FOR_MEMSET_TO_BE_FAST) {
- memset(vb - count, kLine_Verb, count - 1);
- } else {
- for (int i = 1; i < count; ++i) {
- vb[~i] = kLine_Verb;
- }
- }
- fSegmentMask |= kLine_SegmentMask;
+ SkPoint* p = ed.growForRepeatedVerb(kLine_Verb, count - 1);
+ memcpy(p, &pts[1], (count-1) * sizeof(SkPoint));
}
+
if (close) {
- vb[~count] = kClose_Verb;
+ ed.growForVerb(kClose_Verb);
}
DIRTY_AFTER_EDIT;
@@ -1343,11 +1315,21 @@ void SkPath::addArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle
SkPoint pts[kSkBuildQuadArcStorage];
int count = build_arc_points(oval, startAngle, sweepAngle, pts);
- this->incReserve(count);
- this->moveTo(pts[0]);
- for (int i = 1; i < count; i += 2) {
- this->quadTo(pts[i], pts[i+1]);
+ SkDEBUGCODE(this->validate();)
+ SkASSERT(count & 1);
+
+ fLastMoveToIndex = fPathRef->countPoints();
+
+ SkPathRef::Editor ed(&fPathRef, 1+(count-1)/2, count);
+
+ ed.growForVerb(kMove_Verb)->set(pts[0].fX, pts[0].fY);
+ if (count > 1) {
+ SkPoint* p = ed.growForRepeatedVerb(kQuad_Verb, (count-1)/2);
+ memcpy(p, &pts[1], (count-1) * sizeof(SkPoint));
}
+
+ DIRTY_AFTER_EDIT;
+ SkDEBUGCODE(this->validate();)
}
/*
@@ -1671,7 +1653,6 @@ void SkPath::transform(const SkMatrix& matrix, SkPath* dst) const {
if (this != dst) {
dst->fFillType = fFillType;
- dst->fSegmentMask = fSegmentMask;
dst->fConvexity = fConvexity;
}
@@ -2045,7 +2026,6 @@ size_t SkPath::writeToMemory(void* storage) const {
int32_t packed = (fConvexity << kConvexity_SerializationShift) |
(fFillType << kFillType_SerializationShift) |
- (fSegmentMask << kSegmentMask_SerializationShift) |
(fDirection << kDirection_SerializationShift)
#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TOO
| (0x1 << kNewFormat_SerializationShift)
@@ -2070,7 +2050,6 @@ size_t SkPath::readFromMemory(const void* storage, size_t length) {
fConvexity = (packed >> kConvexity_SerializationShift) & 0xFF;
fFillType = (packed >> kFillType_SerializationShift) & 0xFF;
- fSegmentMask = (packed >> kSegmentMask_SerializationShift) & 0xF;
fDirection = (packed >> kDirection_SerializationShift) & 0x3;
#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TOO
bool newFormat = (packed >> kNewFormat_SerializationShift) & 1;
@@ -2201,34 +2180,6 @@ void SkPath::validate() const {
}
}
}
-
- uint32_t mask = 0;
- const uint8_t* verbs = const_cast<const SkPathRef*>(fPathRef.get())->verbs();
- for (int i = 0; i < fPathRef->countVerbs(); i++) {
- switch (verbs[~i]) {
- case kLine_Verb:
- mask |= kLine_SegmentMask;
- break;
- case kQuad_Verb:
- mask |= kQuad_SegmentMask;
- break;
- case kConic_Verb:
- mask |= kConic_SegmentMask;
- break;
- case kCubic_Verb:
- mask |= kCubic_SegmentMask;
- case kMove_Verb: // these verbs aren't included in the segment mask.
- case kClose_Verb:
- break;
- case kDone_Verb:
- SkDEBUGFAIL("Done verb shouldn't be recorded.");
- break;
- default:
- SkDEBUGFAIL("Unknown Verb");
- break;
- }
- }
- SkASSERT(mask == fSegmentMask);
#endif // SK_DEBUG_PATH
}
#endif // SK_DEBUG
diff --git a/core/SkPathRef.cpp b/core/SkPathRef.cpp
index a02df302..0711e3f0 100644
--- a/core/SkPathRef.cpp
+++ b/core/SkPathRef.cpp
@@ -24,17 +24,9 @@ SkPathRef::Editor::Editor(SkAutoTUnref<SkPathRef>* pathRef,
}
fPathRef = *pathRef;
fPathRef->fGenerationID = 0;
- fPathRef->fIsOval = false;
SkDEBUGCODE(sk_atomic_inc(&fPathRef->fEditorsAttached);)
}
-SkPoint* SkPathRef::Editor::growForConic(SkScalar w) {
- SkDEBUGCODE(fPathRef->validate();)
- SkPoint* pts = fPathRef->growForVerb(SkPath::kConic_Verb);
- *fPathRef->fConicWeights.append() = w;
- return pts;
-}
-
//////////////////////////////////////////////////////////////////////////////
void SkPathRef::CreateEmptyImpl(SkPathRef** empty) {
*empty = SkNEW(SkPathRef);
@@ -105,6 +97,8 @@ void SkPathRef::CreateTransformedCopy(SkAutoTUnref<SkPathRef>* dst,
(*dst)->fBoundsIsDirty = true;
}
+ (*dst)->fSegmentMask = src.fSegmentMask;
+
// It's an oval only if it stays a rect.
(*dst)->fIsOval = src.fIsOval && matrix.rectStaysRect();
@@ -118,6 +112,7 @@ SkPathRef* SkPathRef::CreateFromBuffer(SkRBuffer* buffer
) {
SkPathRef* ref = SkNEW(SkPathRef);
bool isOval;
+ uint8_t segmentMask;
int32_t packed;
if (!buffer->readS32(&packed)) {
@@ -130,9 +125,11 @@ SkPathRef* SkPathRef::CreateFromBuffer(SkRBuffer* buffer
#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TOO
if (newFormat) {
#endif
+ segmentMask = (packed >> kSegmentMask_SerializationShift) & 0xF;
isOval = (packed >> kIsOval_SerializationShift) & 1;
#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TOO
} else {
+ segmentMask = (oldPacked >> SkPath::kOldSegmentMask_SerializationShift) & 0xF;
isOval = (oldPacked >> SkPath::kOldIsOval_SerializationShift) & 1;
}
#endif
@@ -159,6 +156,9 @@ SkPathRef* SkPathRef::CreateFromBuffer(SkRBuffer* buffer
return NULL;
}
ref->fBoundsIsDirty = false;
+
+ // resetToSize clears fSegmentMask and fIsOval
+ ref->fSegmentMask = segmentMask;
ref->fIsOval = isOval;
return ref;
}
@@ -172,6 +172,7 @@ void SkPathRef::Rewind(SkAutoTUnref<SkPathRef>* pathRef) {
(*pathRef)->fFreeSpace = (*pathRef)->currSize();
(*pathRef)->fGenerationID = 0;
(*pathRef)->fConicWeights.rewind();
+ (*pathRef)->fSegmentMask = 0;
(*pathRef)->fIsOval = false;
SkDEBUGCODE((*pathRef)->validate();)
} else {
@@ -185,6 +186,14 @@ void SkPathRef::Rewind(SkAutoTUnref<SkPathRef>* pathRef) {
bool SkPathRef::operator== (const SkPathRef& ref) const {
SkDEBUGCODE(this->validate();)
SkDEBUGCODE(ref.validate();)
+
+ // We explicitly check fSegmentMask as a quick-reject. We could skip it,
+ // since it is only a cache of info in the fVerbs, but its a fast way to
+ // notice a difference
+ if (fSegmentMask != ref.fSegmentMask) {
+ return false;
+ }
+
bool genIDMatch = fGenerationID && fGenerationID == ref.fGenerationID;
#ifdef SK_RELEASE
if (genIDMatch) {
@@ -222,7 +231,7 @@ bool SkPathRef::operator== (const SkPathRef& ref) const {
return true;
}
-void SkPathRef::writeToBuffer(SkWBuffer* buffer) {
+void SkPathRef::writeToBuffer(SkWBuffer* buffer) const {
SkDEBUGCODE(this->validate();)
SkDEBUGCODE(size_t beforePos = buffer->pos();)
@@ -231,7 +240,8 @@ void SkPathRef::writeToBuffer(SkWBuffer* buffer) {
const SkRect& bounds = this->getBounds();
int32_t packed = ((fIsFinite & 1) << kIsFinite_SerializationShift) |
- ((fIsOval & 1) << kIsOval_SerializationShift);
+ ((fIsOval & 1) << kIsOval_SerializationShift) |
+ (fSegmentMask << kSegmentMask_SerializationShift);
buffer->write32(packed);
// TODO: write gen ID here. Problem: We don't know if we're cross process or not from
@@ -248,7 +258,7 @@ void SkPathRef::writeToBuffer(SkWBuffer* buffer) {
SkASSERT(buffer->pos() - beforePos == (size_t) this->writeSize());
}
-uint32_t SkPathRef::writeSize() {
+uint32_t SkPathRef::writeSize() const {
return uint32_t(5 * sizeof(uint32_t) +
fVerbCnt * sizeof(uint8_t) +
fPointCnt * sizeof(SkPoint) +
@@ -273,11 +283,91 @@ void SkPathRef::copy(const SkPathRef& ref,
fBounds = ref.fBounds;
fIsFinite = ref.fIsFinite;
}
+ fSegmentMask = ref.fSegmentMask;
fIsOval = ref.fIsOval;
SkDEBUGCODE(this->validate();)
}
-SkPoint* SkPathRef::growForVerb(int /* SkPath::Verb*/ verb) {
+SkPoint* SkPathRef::growForRepeatedVerb(int /*SkPath::Verb*/ verb,
+ int numVbs,
+ SkScalar** weights) {
+ // This value is just made-up for now. When count is 4, calling memset was much
+ // slower than just writing the loop. This seems odd, and hopefully in the
+ // future this will appear to have been a fluke...
+ static const unsigned int kMIN_COUNT_FOR_MEMSET_TO_BE_FAST = 16;
+
+ SkDEBUGCODE(this->validate();)
+ int pCnt;
+ bool dirtyAfterEdit = true;
+ switch (verb) {
+ case SkPath::kMove_Verb:
+ pCnt = numVbs;
+ dirtyAfterEdit = false;
+ break;
+ case SkPath::kLine_Verb:
+ fSegmentMask |= SkPath::kLine_SegmentMask;
+ pCnt = numVbs;
+ break;
+ case SkPath::kQuad_Verb:
+ fSegmentMask |= SkPath::kQuad_SegmentMask;
+ pCnt = 2 * numVbs;
+ break;
+ case SkPath::kConic_Verb:
+ fSegmentMask |= SkPath::kConic_SegmentMask;
+ pCnt = 2 * numVbs;
+ break;
+ case SkPath::kCubic_Verb:
+ fSegmentMask |= SkPath::kCubic_SegmentMask;
+ pCnt = 3 * numVbs;
+ break;
+ case SkPath::kClose_Verb:
+ SkDEBUGFAIL("growForRepeatedVerb called for kClose_Verb");
+ pCnt = 0;
+ dirtyAfterEdit = false;
+ break;
+ case SkPath::kDone_Verb:
+ SkDEBUGFAIL("growForRepeatedVerb called for kDone");
+ // fall through
+ default:
+ SkDEBUGFAIL("default should not be reached");
+ pCnt = 0;
+ dirtyAfterEdit = false;
+ }
+
+ size_t space = numVbs * sizeof(uint8_t) + pCnt * sizeof (SkPoint);
+ this->makeSpace(space);
+
+ SkPoint* ret = fPoints + fPointCnt;
+ uint8_t* vb = fVerbs - fVerbCnt;
+
+ // cast to unsigned, so if kMIN_COUNT_FOR_MEMSET_TO_BE_FAST is defined to
+ // be 0, the compiler will remove the test/branch entirely.
+ if ((unsigned)numVbs >= kMIN_COUNT_FOR_MEMSET_TO_BE_FAST) {
+ memset(vb - numVbs, verb, numVbs);
+ } else {
+ for (int i = 0; i < numVbs; ++i) {
+ vb[~i] = verb;
+ }
+ }
+
+ fVerbCnt += numVbs;
+ fPointCnt += pCnt;
+ fFreeSpace -= space;
+ fBoundsIsDirty = true; // this also invalidates fIsFinite
+ if (dirtyAfterEdit) {
+ fIsOval = false;
+ }
+
+ if (SkPath::kConic_Verb == verb) {
+ SkASSERT(NULL != weights);
+ *weights = fConicWeights.append(numVbs);
+ }
+
+ SkDEBUGCODE(this->validate();)
+ return ret;
+}
+
+SkPoint* SkPathRef::growForVerb(int /* SkPath::Verb*/ verb, SkScalar weight) {
SkDEBUGCODE(this->validate();)
int pCnt;
bool dirtyAfterEdit = true;
@@ -287,14 +377,19 @@ SkPoint* SkPathRef::growForVerb(int /* SkPath::Verb*/ verb) {
dirtyAfterEdit = false;
break;
case SkPath::kLine_Verb:
+ fSegmentMask |= SkPath::kLine_SegmentMask;
pCnt = 1;
break;
case SkPath::kQuad_Verb:
- // fall through
+ fSegmentMask |= SkPath::kQuad_SegmentMask;
+ pCnt = 2;
+ break;
case SkPath::kConic_Verb:
+ fSegmentMask |= SkPath::kConic_SegmentMask;
pCnt = 2;
break;
case SkPath::kCubic_Verb:
+ fSegmentMask |= SkPath::kCubic_SegmentMask;
pCnt = 3;
break;
case SkPath::kClose_Verb:
@@ -320,6 +415,11 @@ SkPoint* SkPathRef::growForVerb(int /* SkPath::Verb*/ verb) {
if (dirtyAfterEdit) {
fIsOval = false;
}
+
+ if (SkPath::kConic_Verb == verb) {
+ *fConicWeights.append() = weight;
+ }
+
SkDEBUGCODE(this->validate();)
return ret;
}
@@ -369,5 +469,36 @@ void SkPathRef::validate() const {
}
SkASSERT(SkToBool(fIsFinite) == isFinite);
}
+
+#ifdef SK_DEBUG_PATH
+ uint32_t mask = 0;
+ for (int i = 0; i < fVerbCnt; ++i) {
+ switch (fVerbs[~i]) {
+ case SkPath::kMove_Verb:
+ break;
+ case SkPath::kLine_Verb:
+ mask |= SkPath::kLine_SegmentMask;
+ break;
+ case SkPath::kQuad_Verb:
+ mask |= SkPath::kQuad_SegmentMask;
+ break;
+ case SkPath::kConic_Verb:
+ mask |= SkPath::kConic_SegmentMask;
+ break;
+ case SkPath::kCubic_Verb:
+ mask |= SkPath::kCubic_SegmentMask;
+ break;
+ case SkPath::kClose_Verb:
+ break;
+ case SkPath::kDone_Verb:
+ SkDEBUGFAIL("Done verb shouldn't be recorded.");
+ break;
+ default:
+ SkDEBUGFAIL("Unknown Verb");
+ break;
+ }
+ }
+ SkASSERT(mask == fSegmentMask);
+#endif // SK_DEBUG_PATH
}
#endif
diff --git a/core/SkPixelRef.cpp b/core/SkPixelRef.cpp
index e93882a4..6cc67d89 100644
--- a/core/SkPixelRef.cpp
+++ b/core/SkPixelRef.cpp
@@ -122,6 +122,7 @@ SkPixelRef::SkPixelRef(SkBaseMutex* mutex) {
SkPixelRef::SkPixelRef(SkFlattenableReadBuffer& buffer, SkBaseMutex* mutex)
: INHERITED(buffer) {
this->setMutex(mutex);
+ fInfo.unflatten(buffer);
fPixels = NULL;
fColorTable = NULL; // we do not track ownership of this
fLockCount = 0;
@@ -160,6 +161,7 @@ void SkPixelRef::setPreLocked(void* pixels, SkColorTable* ctable) {
void SkPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
+ fInfo.flatten(buffer);
buffer.writeBool(fIsImmutable);
// We write the gen ID into the picture for within-process recording. This
// is safe since the same genID will never refer to two different sets of
@@ -182,6 +184,10 @@ void SkPixelRef::lockPixels() {
if (1 == ++fLockCount) {
fPixels = this->onLockPixels(&fColorTable);
+ // If onLockPixels failed, it will return NULL
+ if (NULL == fPixels) {
+ fColorTable = NULL;
+ }
}
}
}
@@ -194,9 +200,14 @@ void SkPixelRef::unlockPixels() {
SkASSERT(fLockCount > 0);
if (0 == --fLockCount) {
- this->onUnlockPixels();
- fPixels = NULL;
- fColorTable = NULL;
+ // don't call onUnlockPixels unless onLockPixels succeeded
+ if (fPixels) {
+ this->onUnlockPixels();
+ fPixels = NULL;
+ fColorTable = NULL;
+ } else {
+ SkASSERT(NULL == fColorTable);
+ }
}
}
}
diff --git a/core/SkScaledImageCache.cpp b/core/SkScaledImageCache.cpp
index b3956f4a..2529b5f8 100644
--- a/core/SkScaledImageCache.cpp
+++ b/core/SkScaledImageCache.cpp
@@ -209,7 +209,6 @@ private:
SkDiscardableMemory* fDM;
size_t fRB;
bool fFirstTime;
- bool fIsLocked;
typedef SkPixelRef INHERITED;
};
@@ -225,7 +224,6 @@ SkOneShotDiscardablePixelRef::SkOneShotDiscardablePixelRef(const SkImageInfo& in
SkASSERT(dm->data());
fFirstTime = true;
- fIsLocked = false;
}
SkOneShotDiscardablePixelRef::~SkOneShotDiscardablePixelRef() {
@@ -235,21 +233,28 @@ SkOneShotDiscardablePixelRef::~SkOneShotDiscardablePixelRef() {
void* SkOneShotDiscardablePixelRef::onLockPixels(SkColorTable** ctable) {
if (fFirstTime) {
// we're already locked
+ SkASSERT(fDM->data());
fFirstTime = false;
return fDM->data();
}
- SkASSERT(!fIsLocked);
- fIsLocked = fDM->lock();
- return fIsLocked ? fDM->data() : NULL;
+ // A previous call to onUnlock may have deleted our DM, so check for that
+ if (NULL == fDM) {
+ return NULL;
+ }
+
+ if (!fDM->lock()) {
+ // since it failed, we delete it now, to free-up the resource
+ delete fDM;
+ fDM = NULL;
+ return NULL;
+ }
+ return fDM->data();
}
void SkOneShotDiscardablePixelRef::onUnlockPixels() {
SkASSERT(!fFirstTime);
- if (fIsLocked) {
- fIsLocked = false;
- fDM->unlock();
- }
+ fDM->unlock();
}
size_t SkOneShotDiscardablePixelRef::getAllocatedSizeInBytes() const {
@@ -613,6 +618,8 @@ void SkScaledImageCache::addToHead(Rec* rec) {
this->validate();
}
+///////////////////////////////////////////////////////////////////////////////
+
#ifdef SK_DEBUG
void SkScaledImageCache::validate() const {
if (NULL == fHead) {
@@ -658,6 +665,21 @@ void SkScaledImageCache::validate() const {
}
#endif
+void SkScaledImageCache::dump() const {
+ this->validate();
+
+ const Rec* rec = fHead;
+ int locked = 0;
+ while (rec) {
+ locked += rec->fLockCount > 0;
+ rec = rec->fNext;
+ }
+
+ SkDebugf("SkScaledImageCache: count=%d bytes=%d locked=%d %s\n",
+ fCount, fBytesUsed, locked,
+ fDiscardableFactory ? "discardable" : "malloc");
+}
+
///////////////////////////////////////////////////////////////////////////////
#include "SkThread.h"
@@ -730,7 +752,9 @@ SkScaledImageCache::ID* SkScaledImageCache::AddAndLockMip(const SkBitmap& orig,
void SkScaledImageCache::Unlock(SkScaledImageCache::ID* id) {
SkAutoMutexAcquire am(gMutex);
- return get_cache()->unlock(id);
+ get_cache()->unlock(id);
+
+// get_cache()->dump();
}
size_t SkScaledImageCache::GetBytesUsed() {
@@ -753,6 +777,11 @@ SkBitmap::Allocator* SkScaledImageCache::GetAllocator() {
return get_cache()->allocator();
}
+void SkScaledImageCache::Dump() {
+ SkAutoMutexAcquire am(gMutex);
+ get_cache()->dump();
+}
+
///////////////////////////////////////////////////////////////////////////////
#include "SkGraphics.h"
diff --git a/core/SkScaledImageCache.h b/core/SkScaledImageCache.h
index 311db325..fe072306 100644
--- a/core/SkScaledImageCache.h
+++ b/core/SkScaledImageCache.h
@@ -66,6 +66,11 @@ public:
static SkBitmap::Allocator* GetAllocator();
+ /**
+ * Call SkDebugf() with diagnostic information about the state of the cache
+ */
+ static void Dump();
+
///////////////////////////////////////////////////////////////////////////
/**
@@ -151,6 +156,11 @@ public:
SkBitmap::Allocator* allocator() const { return fAllocator; };
+ /**
+ * Call SkDebugf() with diagnostic information about the state of the cache
+ */
+ void dump() const;
+
public:
struct Rec;
struct Key;
@@ -174,6 +184,7 @@ private:
Rec* findAndLock(const Key& key);
ID* addAndLock(Rec* rec);
+ void purgeRec(Rec*);
void purgeAsNeeded();
// linklist management
diff --git a/effects/SkDisplacementMapEffect.cpp b/effects/SkDisplacementMapEffect.cpp
index 6e5c910e..f43287c4 100644
--- a/effects/SkDisplacementMapEffect.cpp
+++ b/effects/SkDisplacementMapEffect.cpp
@@ -205,6 +205,14 @@ bool SkDisplacementMapEffect::onFilterImage(Proxy* proxy,
if (!this->applyCropRect(&bounds, ctm)) {
return false;
}
+ SkIRect displBounds;
+ displ.getBounds(&displBounds);
+ if (!this->applyCropRect(&displBounds, ctm)) {
+ return false;
+ }
+ if (!bounds.intersect(displBounds)) {
+ return false;
+ }
dst->setConfig(color.config(), bounds.width(), bounds.height());
dst->allocPixels();
@@ -338,6 +346,14 @@ bool SkDisplacementMapEffect::filterImageGPU(Proxy* proxy, const SkBitmap& src,
if (!this->applyCropRect(&bounds, ctm)) {
return false;
}
+ SkIRect displBounds;
+ displacementBM.getBounds(&displBounds);
+ if (!this->applyCropRect(&displBounds, ctm)) {
+ return false;
+ }
+ if (!bounds.intersect(displBounds)) {
+ return false;
+ }
SkRect srcRect = SkRect::Make(bounds);
SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
context->drawRectToRect(paint, dstRect, srcRect);
diff --git a/effects/SkPictureImageFilter.cpp b/effects/SkPictureImageFilter.cpp
new file mode 100644
index 00000000..5b4af654
--- /dev/null
+++ b/effects/SkPictureImageFilter.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2013 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkPictureImageFilter.h"
+#include "SkDevice.h"
+#include "SkCanvas.h"
+#include "SkFlattenableBuffers.h"
+#include "SkValidationUtils.h"
+
+SkPictureImageFilter::SkPictureImageFilter(SkPicture* picture)
+ : INHERITED(0, 0),
+ fPicture(picture),
+ fRect(SkRect::MakeWH(picture ? SkIntToScalar(picture->width()) : 0,
+ picture ? SkIntToScalar(picture->height()) : 0)) {
+ SkSafeRef(fPicture);
+}
+
+SkPictureImageFilter::SkPictureImageFilter(SkPicture* picture, const SkRect& rect)
+ : INHERITED(0, 0),
+ fPicture(picture),
+ fRect(rect) {
+ SkSafeRef(fPicture);
+}
+
+SkPictureImageFilter::~SkPictureImageFilter() {
+ SkSafeUnref(fPicture);
+}
+
+SkPictureImageFilter::SkPictureImageFilter(SkFlattenableReadBuffer& buffer)
+ : INHERITED(0, buffer),
+ fPicture(NULL) {
+ // FIXME: unflatten picture here.
+ buffer.readRect(&fRect);
+}
+
+void SkPictureImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
+ this->INHERITED::flatten(buffer);
+ // FIXME: flatten picture here.
+ buffer.writeRect(fRect);
+}
+
+bool SkPictureImageFilter::onFilterImage(Proxy* proxy, const SkBitmap&, const SkMatrix& matrix,
+ SkBitmap* result, SkIPoint* offset) {
+ if (!fPicture) {
+ return true;
+ }
+
+ SkRect floatBounds;
+ SkIRect bounds;
+ matrix.mapRect(&floatBounds, fRect);
+ floatBounds.roundOut(&bounds);
+
+ if (bounds.isEmpty()) {
+ return true;
+ }
+
+ SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height()));
+ if (NULL == device.get()) {
+ return false;
+ }
+
+ SkCanvas canvas(device.get());
+ SkPaint paint;
+
+ canvas.translate(-SkIntToScalar(bounds.fLeft), -SkIntToScalar(bounds.fTop));
+ canvas.concat(matrix);
+ canvas.drawPicture(*fPicture);
+
+ *result = device.get()->accessBitmap(false);
+ offset->fX += bounds.fLeft;
+ offset->fY += bounds.fTop;
+ return true;
+}
diff --git a/effects/gradients/SkGradientShader.cpp b/effects/gradients/SkGradientShader.cpp
index 27761993..5d200d18 100644
--- a/effects/gradients/SkGradientShader.cpp
+++ b/effects/gradients/SkGradientShader.cpp
@@ -513,13 +513,14 @@ const uint16_t* SkGradientShaderBase::getCache16() const {
const SkPMColor* SkGradientShaderBase::getCache32() const {
if (fCache32 == NULL) {
- // double the count for dither entries
- const int entryCount = kCache32Count * 4;
- const size_t allocSize = sizeof(SkPMColor) * entryCount;
+ SkImageInfo info;
+ info.fWidth = kCache32Count;
+ info.fHeight = 4; // for our 4 dither rows
+ info.fAlphaType = kPremul_SkAlphaType;
+ info.fColorType = kPMColor_SkColorType;
if (NULL == fCache32PixelRef) {
- fCache32PixelRef = SkNEW_ARGS(SkMallocPixelRef,
- (NULL, allocSize, NULL));
+ fCache32PixelRef = SkMallocPixelRef::NewAllocate(info, 0, NULL);
}
fCache32 = (SkPMColor*)fCache32PixelRef->getAddr();
if (fColorCount == 2) {
@@ -541,8 +542,7 @@ const SkPMColor* SkGradientShaderBase::getCache32() const {
}
if (fMapper) {
- SkMallocPixelRef* newPR = SkNEW_ARGS(SkMallocPixelRef,
- (NULL, allocSize, NULL));
+ 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;
diff --git a/gpu/GrSurface.cpp b/gpu/GrSurface.cpp
index fed95f23..1fcc4ff1 100644
--- a/gpu/GrSurface.cpp
+++ b/gpu/GrSurface.cpp
@@ -8,9 +8,19 @@
#include "GrSurface.h"
#include "SkBitmap.h"
+#include "SkGr.h"
#include "SkImageEncoder.h"
#include <stdio.h>
+void GrSurface::asImageInfo(SkImageInfo* info) const {
+ if (!GrPixelConfig2ColorType(this->config(), &info->fColorType)) {
+ sk_throw();
+ }
+ info->fWidth = this->width();
+ info->fHeight = this->height();
+ info->fAlphaType = kPremul_SkAlphaType;
+}
+
bool GrSurface::savePixels(const char* filename) {
SkBitmap bm;
bm.setConfig(SkBitmap::kARGB_8888_Config, this->width(), this->height());
diff --git a/gpu/SkGpuDevice.cpp b/gpu/SkGpuDevice.cpp
index ce02f2c5..a413d042 100644
--- a/gpu/SkGpuDevice.cpp
+++ b/gpu/SkGpuDevice.cpp
@@ -214,7 +214,10 @@ void SkGpuDevice::initFromRenderTarget(GrContext* context,
if (NULL == surface) {
surface = fRenderTarget;
}
- SkPixelRef* pr = SkNEW_ARGS(SkGrPixelRef, (surface, cached));
+
+ SkImageInfo info;
+ surface->asImageInfo(&info);
+ SkPixelRef* pr = SkNEW_ARGS(SkGrPixelRef, (info, surface, cached));
this->setPixelRef(pr, 0)->unref();
}
@@ -224,8 +227,8 @@ SkGpuDevice::SkGpuDevice(GrContext* context,
int width,
int height,
int sampleCount)
- : SkBitmapDevice(make_bitmap(config, width, height, false /*isOpaque*/)) {
-
+ : SkBitmapDevice(make_bitmap(config, width, height, false /*isOpaque*/))
+{
fDrawProcs = NULL;
fContext = context;
@@ -245,6 +248,14 @@ SkGpuDevice::SkGpuDevice(GrContext* context,
desc.fConfig = SkBitmapConfig2GrPixelConfig(config);
desc.fSampleCnt = sampleCount;
+ SkImageInfo info;
+ if (!GrPixelConfig2ColorType(desc.fConfig, &info.fColorType)) {
+ sk_throw();
+ }
+ info.fWidth = width;
+ info.fHeight = height;
+ info.fAlphaType = kPremul_SkAlphaType;
+
SkAutoTUnref<GrTexture> texture(fContext->createUncachedTexture(desc, NULL, 0));
if (NULL != texture) {
@@ -254,7 +265,7 @@ SkGpuDevice::SkGpuDevice(GrContext* context,
SkASSERT(NULL != fRenderTarget);
// wrap the bitmap with a pixelref to expose our texture
- SkGrPixelRef* pr = SkNEW_ARGS(SkGrPixelRef, (texture));
+ SkGrPixelRef* pr = SkNEW_ARGS(SkGrPixelRef, (info, texture));
this->setPixelRef(pr, 0)->unref();
} else {
GrPrintf("--- failed to create gpu-offscreen [%d %d]\n",
@@ -840,11 +851,12 @@ bool create_mask_GPU(GrContext* context,
}
SkBitmap wrap_texture(GrTexture* texture) {
+ SkImageInfo info;
+ texture->asImageInfo(&info);
+
SkBitmap result;
- bool dummy;
- SkBitmap::Config config = grConfig2skConfig(texture->config(), &dummy);
- result.setConfig(config, texture->width(), texture->height());
- result.setPixelRef(SkNEW_ARGS(SkGrPixelRef, (texture)))->unref();
+ result.setConfig(info);
+ result.setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, texture)))->unref();
return result;
}
diff --git a/gpu/SkGr.cpp b/gpu/SkGr.cpp
index c7ae0c8f..a3f0eefa 100644
--- a/gpu/SkGr.cpp
+++ b/gpu/SkGr.cpp
@@ -258,3 +258,33 @@ GrPixelConfig SkBitmapConfig2GrPixelConfig(SkBitmap::Config config) {
return kUnknown_GrPixelConfig;
}
}
+
+bool GrPixelConfig2ColorType(GrPixelConfig config, SkColorType* ctOut) {
+ SkColorType ct;
+ switch (config) {
+ case kAlpha_8_GrPixelConfig:
+ ct = kAlpha_8_SkColorType;
+ break;
+ case kIndex_8_GrPixelConfig:
+ ct = kIndex_8_SkColorType;
+ break;
+ case kRGB_565_GrPixelConfig:
+ ct = kRGB_565_SkColorType;
+ break;
+ case kRGBA_4444_GrPixelConfig:
+ ct = kARGB_4444_SkColorType;
+ break;
+ case kRGBA_8888_GrPixelConfig:
+ ct = kRGBA_8888_SkColorType;
+ break;
+ case kBGRA_8888_GrPixelConfig:
+ ct = kBGRA_8888_SkColorType;
+ break;
+ default:
+ return false;
+ }
+ if (ctOut) {
+ *ctOut = ct;
+ }
+ return true;
+}
diff --git a/gpu/SkGrPixelRef.cpp b/gpu/SkGrPixelRef.cpp
index 01294266..ddd60ff8 100644
--- a/gpu/SkGrPixelRef.cpp
+++ b/gpu/SkGrPixelRef.cpp
@@ -18,11 +18,10 @@
// to avoid deadlock with the default one provided by SkPixelRef.
SK_DECLARE_STATIC_MUTEX(gROLockPixelsPixelRefMutex);
-SkROLockPixelsPixelRef::SkROLockPixelsPixelRef() : INHERITED(&gROLockPixelsPixelRefMutex) {
-}
+SkROLockPixelsPixelRef::SkROLockPixelsPixelRef(const SkImageInfo& info)
+ : INHERITED(info, &gROLockPixelsPixelRefMutex) {}
-SkROLockPixelsPixelRef::~SkROLockPixelsPixelRef() {
-}
+SkROLockPixelsPixelRef::~SkROLockPixelsPixelRef() {}
void* SkROLockPixelsPixelRef::onLockPixels(SkColorTable** ctable) {
if (ctable) {
@@ -76,6 +75,14 @@ static SkGrPixelRef* copyToTexturePixelRef(GrTexture* texture, SkBitmap::Config
desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
desc.fConfig = SkBitmapConfig2GrPixelConfig(dstConfig);
+ SkImageInfo info;
+ if (!GrPixelConfig2ColorType(desc.fConfig, &info.fColorType)) {
+ return NULL;
+ }
+ info.fWidth = desc.fWidth;
+ info.fHeight = desc.fHeight;
+ info.fAlphaType = kPremul_SkAlphaType;
+
GrTexture* dst = context->createUncachedTexture(desc, NULL, 0);
if (NULL == dst) {
return NULL;
@@ -93,31 +100,15 @@ static SkGrPixelRef* copyToTexturePixelRef(GrTexture* texture, SkBitmap::Config
dst->releaseRenderTarget();
#endif
- SkGrPixelRef* pixelRef = SkNEW_ARGS(SkGrPixelRef, (dst));
+ SkGrPixelRef* pixelRef = SkNEW_ARGS(SkGrPixelRef, (info, dst));
SkSafeUnref(dst);
return pixelRef;
}
///////////////////////////////////////////////////////////////////////////////
-SkGrPixelRef::SkGrPixelRef(GrSurface* surface, bool transferCacheLock) {
- // TODO: figure out if this is responsible for Chrome canvas errors
-#if 0
- // The GrTexture has a ref to the GrRenderTarget but not vice versa.
- // If the GrTexture exists take a ref to that (rather than the render
- // target)
- fSurface = surface->asTexture();
-#else
- fSurface = NULL;
-#endif
- if (NULL == fSurface) {
- fSurface = surface;
- }
- fUnlock = transferCacheLock;
- SkSafeRef(surface);
-}
-
-SkGrPixelRef::SkGrPixelRef(const SkImageInfo&, GrSurface* surface, bool transferCacheLock) {
+SkGrPixelRef::SkGrPixelRef(const SkImageInfo& info, GrSurface* surface,
+ bool transferCacheLock) : INHERITED(info) {
// TODO: figure out if this is responsible for Chrome canvas errors
#if 0
// The GrTexture has a ref to the GrRenderTarget but not vice versa.
diff --git a/image/SkDataPixelRef.cpp b/image/SkDataPixelRef.cpp
index 7897bf93..c8bfe808 100644
--- a/image/SkDataPixelRef.cpp
+++ b/image/SkDataPixelRef.cpp
@@ -9,7 +9,10 @@
#include "SkData.h"
#include "SkFlattenableBuffers.h"
-SkDataPixelRef::SkDataPixelRef(SkData* data) : fData(data) {
+SkDataPixelRef::SkDataPixelRef(const SkImageInfo& info, SkData* data)
+ : INHERITED(info)
+ , fData(data)
+{
fData->ref();
this->setPreLocked(const_cast<void*>(fData->data()), NULL);
}
diff --git a/image/SkDataPixelRef.h b/image/SkDataPixelRef.h
index 50c88571..0f8269c8 100644
--- a/image/SkDataPixelRef.h
+++ b/image/SkDataPixelRef.h
@@ -14,7 +14,7 @@ class SkData;
class SkDataPixelRef : public SkPixelRef {
public:
- SkDataPixelRef(SkData* data);
+ SkDataPixelRef(const SkImageInfo&, SkData* data);
virtual ~SkDataPixelRef();
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDataPixelRef)
diff --git a/image/SkImage_Raster.cpp b/image/SkImage_Raster.cpp
index a872ae36..807c19e7 100644
--- a/image/SkImage_Raster.cpp
+++ b/image/SkImage_Raster.cpp
@@ -84,10 +84,8 @@ SkImage* SkImage_Raster::NewEmpty() {
SkImage_Raster::SkImage_Raster(const Info& info, SkData* data, size_t rowBytes)
: INHERITED(info.fWidth, info.fHeight) {
- SkBitmap::Config config = SkImageInfoToBitmapConfig(info);
-
- fBitmap.setConfig(config, info.fWidth, info.fHeight, rowBytes, info.fAlphaType);
- fBitmap.setPixelRef(SkNEW_ARGS(SkDataPixelRef, (data)))->unref();
+ fBitmap.setConfig(info, rowBytes);
+ fBitmap.setPixelRef(SkNEW_ARGS(SkDataPixelRef, (info, data)))->unref();
fBitmap.setImmutable();
}
diff --git a/image/SkSurface_Raster.cpp b/image/SkSurface_Raster.cpp
index 27db504d..61ade6f4 100644
--- a/image/SkSurface_Raster.cpp
+++ b/image/SkSurface_Raster.cpp
@@ -155,19 +155,9 @@ SkSurface* SkSurface::NewRaster(const SkImageInfo& info) {
return NULL;
}
- static const size_t kMaxTotalSize = SK_MaxS32;
- size_t rowBytes = SkImageMinRowBytes(info);
- uint64_t size64 = (uint64_t)info.fHeight * rowBytes;
- if (size64 > kMaxTotalSize) {
- return NULL;
- }
-
- size_t size = (size_t)size64;
- void* pixels = sk_malloc_throw(size);
- if (NULL == pixels) {
+ SkAutoTUnref<SkPixelRef> pr(SkMallocPixelRef::NewAllocate(info, 0, NULL));
+ if (NULL == pr.get()) {
return NULL;
}
-
- SkAutoTUnref<SkPixelRef> pr(SkNEW_ARGS(SkMallocPixelRef, (pixels, size, NULL, true)));
- return SkNEW_ARGS(SkSurface_Raster, (info, pr, rowBytes));
+ return SkNEW_ARGS(SkSurface_Raster, (info, pr, info.minRowBytes()));
}
diff --git a/images/SkImageRef.cpp b/images/SkImageRef.cpp
index 1a8284bd..716519f0 100644
--- a/images/SkImageRef.cpp
+++ b/images/SkImageRef.cpp
@@ -18,13 +18,12 @@
///////////////////////////////////////////////////////////////////////////////
-SkImageRef::SkImageRef(SkStreamRewindable* stream, SkBitmap::Config config,
+SkImageRef::SkImageRef(const SkImageInfo& info, SkStreamRewindable* stream,
int sampleSize, SkBaseMutex* mutex)
- : SkPixelRef(mutex), fErrorInDecoding(false) {
+ : SkPixelRef(info, mutex), fErrorInDecoding(false) {
SkASSERT(stream);
stream->ref();
fStream = stream;
- fConfig = config;
fSampleSize = sampleSize;
fDoDither = true;
fPrev = fNext = NULL;
@@ -32,7 +31,7 @@ SkImageRef::SkImageRef(SkStreamRewindable* stream, SkBitmap::Config config,
#ifdef DUMP_IMAGEREF_LIFECYCLE
SkDebugf("add ImageRef %p [%d] data=%d\n",
- this, config, (int)stream->getLength());
+ this, this->info().fColorType, (int)stream->getLength());
#endif
}
@@ -92,14 +91,6 @@ bool SkImageRef::prepareBitmap(SkImageDecoder::Mode mode) {
return false;
}
- /* As soon as we really know our config, we record it, so that on
- subsequent calls to the codec, we are sure we will always get the same
- result.
- */
- if (SkBitmap::kNo_Config != fBitmap.config()) {
- fConfig = fBitmap.config();
- }
-
if (NULL != fBitmap.getPixels() ||
(SkBitmap::kNo_Config != fBitmap.config() &&
SkImageDecoder::kDecodeBounds_Mode == mode)) {
@@ -125,7 +116,7 @@ bool SkImageRef::prepareBitmap(SkImageDecoder::Mode mode) {
codec->setSampleSize(fSampleSize);
codec->setDitherImage(fDoDither);
- if (this->onDecode(codec, fStream, &fBitmap, fConfig, mode)) {
+ if (this->onDecode(codec, fStream, &fBitmap, fBitmap.config(), mode)) {
return true;
}
}
@@ -170,7 +161,6 @@ size_t SkImageRef::ramUsed() const {
SkImageRef::SkImageRef(SkFlattenableReadBuffer& buffer, SkBaseMutex* mutex)
: INHERITED(buffer, mutex), fErrorInDecoding(false) {
- fConfig = (SkBitmap::Config)buffer.readUInt();
fSampleSize = buffer.readInt();
fDoDither = buffer.readBool();
@@ -185,7 +175,6 @@ SkImageRef::SkImageRef(SkFlattenableReadBuffer& buffer, SkBaseMutex* mutex)
void SkImageRef::flatten(SkFlattenableWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
- buffer.writeUInt(fConfig);
buffer.writeInt(fSampleSize);
buffer.writeBool(fDoDither);
// FIXME: Consider moving this logic should go into writeStream itself.
diff --git a/images/SkImageRef_GlobalPool.cpp b/images/SkImageRef_GlobalPool.cpp
index 352dd42d..f91cebab 100644
--- a/images/SkImageRef_GlobalPool.cpp
+++ b/images/SkImageRef_GlobalPool.cpp
@@ -24,10 +24,10 @@ static SkImageRefPool* GetGlobalPool() {
return gPool;
}
-SkImageRef_GlobalPool::SkImageRef_GlobalPool(SkStreamRewindable* stream,
- SkBitmap::Config config,
+SkImageRef_GlobalPool::SkImageRef_GlobalPool(const SkImageInfo& info,
+ SkStreamRewindable* stream,
int sampleSize)
- : SkImageRef(stream, config, sampleSize, &gGlobalPoolMutex) {
+ : SkImageRef(info, stream, sampleSize, &gGlobalPoolMutex) {
SkASSERT(&gGlobalPoolMutex == this->mutex());
SkAutoMutexAcquire ac(gGlobalPoolMutex);
GetGlobalPool()->addToHead(this);
diff --git a/images/SkImageRef_ashmem.cpp b/images/SkImageRef_ashmem.cpp
index 0dba1d11..269199fa 100644
--- a/images/SkImageRef_ashmem.cpp
+++ b/images/SkImageRef_ashmem.cpp
@@ -1,10 +1,10 @@
-
/*
* Copyright 2011 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
+
#include "SkImageRef_ashmem.h"
#include "SkImageDecoder.h"
#include "SkFlattenableBuffers.h"
@@ -31,11 +31,11 @@ static size_t roundToPageSize(size_t size) {
return newsize;
}
-SkImageRef_ashmem::SkImageRef_ashmem(SkStreamRewindable* stream,
- SkBitmap::Config config,
- int sampleSize)
- : SkImageRef(stream, config, sampleSize) {
-
+SkImageRef_ashmem::SkImageRef_ashmem(const SkImageInfo& info,
+ SkStreamRewindable* stream,
+ int sampleSize)
+ : SkImageRef(info, stream, sampleSize)
+{
fRec.fFD = -1;
fRec.fAddr = NULL;
fRec.fSize = 0;
diff --git a/images/SkImageRef_ashmem.h b/images/SkImageRef_ashmem.h
index efee5e75..a2652fbc 100644
--- a/images/SkImageRef_ashmem.h
+++ b/images/SkImageRef_ashmem.h
@@ -19,7 +19,7 @@ struct SkAshmemRec {
class SkImageRef_ashmem : public SkImageRef {
public:
- SkImageRef_ashmem(SkStreamRewindable*, SkBitmap::Config, int sampleSize = 1);
+ SkImageRef_ashmem(const SkImageInfo&, SkStreamRewindable*, int sampleSize = 1);
virtual ~SkImageRef_ashmem();
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkImageRef_ashmem)
diff --git a/lazy/SkCachingPixelRef.cpp b/lazy/SkCachingPixelRef.cpp
index 667a9493..668f57ef 100644
--- a/lazy/SkCachingPixelRef.cpp
+++ b/lazy/SkCachingPixelRef.cpp
@@ -21,20 +21,18 @@ bool SkCachingPixelRef::Install(SkImageGenerator* generator,
return false;
}
SkAutoTUnref<SkCachingPixelRef> ref(SkNEW_ARGS(SkCachingPixelRef,
- (generator,
- info,
- dst->rowBytes())));
+ (info, generator, dst->rowBytes())));
dst->setPixelRef(ref);
return true;
}
-SkCachingPixelRef::SkCachingPixelRef(SkImageGenerator* generator,
- const SkImageInfo& info,
+SkCachingPixelRef::SkCachingPixelRef(const SkImageInfo& info,
+ SkImageGenerator* generator,
size_t rowBytes)
- : fImageGenerator(generator)
+ : INHERITED(info)
+ , fImageGenerator(generator)
, fErrorInDecoding(false)
, fScaledCacheId(NULL)
- , fInfo(info)
, fRowBytes(rowBytes) {
SkASSERT(fImageGenerator != NULL);
}
@@ -44,31 +42,32 @@ SkCachingPixelRef::~SkCachingPixelRef() {
// Assert always unlock before unref.
}
-void* SkCachingPixelRef::onLockPixels(SkColorTable** colorTable) {
- (void)colorTable;
+void* SkCachingPixelRef::onLockPixels(SkColorTable**) {
+ const SkImageInfo& info = this->info();
+
if (fErrorInDecoding) {
return NULL; // don't try again.
}
SkBitmap bitmap;
SkASSERT(NULL == fScaledCacheId);
fScaledCacheId = SkScaledImageCache::FindAndLock(this->getGenerationID(),
- fInfo.fWidth,
- fInfo.fHeight,
+ info.fWidth,
+ info.fHeight,
&bitmap);
if (NULL == fScaledCacheId) {
// Cache has been purged, must re-decode.
- if ((!bitmap.setConfig(fInfo, fRowBytes)) || !bitmap.allocPixels()) {
+ if ((!bitmap.setConfig(info, fRowBytes)) || !bitmap.allocPixels()) {
fErrorInDecoding = true;
return NULL;
}
SkAutoLockPixels autoLockPixels(bitmap);
- if (!fImageGenerator->getPixels(fInfo, bitmap.getPixels(), fRowBytes)) {
+ if (!fImageGenerator->getPixels(info, bitmap.getPixels(), fRowBytes)) {
fErrorInDecoding = true;
return NULL;
}
fScaledCacheId = SkScaledImageCache::AddAndLock(this->getGenerationID(),
- fInfo.fWidth,
- fInfo.fHeight,
+ info.fWidth,
+ info.fHeight,
bitmap);
SkASSERT(fScaledCacheId != NULL);
}
@@ -90,9 +89,7 @@ void* SkCachingPixelRef::onLockPixels(SkColorTable** colorTable) {
}
void SkCachingPixelRef::onUnlockPixels() {
- if (fScaledCacheId != NULL) {
- SkScaledImageCache::Unlock(
- static_cast<SkScaledImageCache::ID*>(fScaledCacheId));
- fScaledCacheId = NULL;
- }
+ SkASSERT(fScaledCacheId != NULL);
+ SkScaledImageCache::Unlock( static_cast<SkScaledImageCache::ID*>(fScaledCacheId));
+ fScaledCacheId = NULL;
}
diff --git a/lazy/SkCachingPixelRef.h b/lazy/SkCachingPixelRef.h
index 4a0387dd..b1f2fcd6 100644
--- a/lazy/SkCachingPixelRef.h
+++ b/lazy/SkCachingPixelRef.h
@@ -58,12 +58,10 @@ private:
SkImageGenerator* const fImageGenerator;
bool fErrorInDecoding;
void* fScaledCacheId;
- const SkImageInfo fInfo;
const size_t fRowBytes;
- SkCachingPixelRef(SkImageGenerator* imageGenerator,
- const SkImageInfo& info,
- size_t rowBytes);
+ SkCachingPixelRef(const SkImageInfo&, SkImageGenerator*, size_t rowBytes);
+
typedef SkPixelRef INHERITED;
};
diff --git a/lazy/SkDiscardableMemoryPool.cpp b/lazy/SkDiscardableMemoryPool.cpp
index a1b2438a..47097098 100644
--- a/lazy/SkDiscardableMemoryPool.cpp
+++ b/lazy/SkDiscardableMemoryPool.cpp
@@ -47,19 +47,23 @@ SkPoolDiscardableMemory::SkPoolDiscardableMemory(SkDiscardableMemoryPool* pool,
}
SkPoolDiscardableMemory::~SkPoolDiscardableMemory() {
+ SkASSERT(!fLocked); // contract for SkDiscardableMemory
fPool->free(this);
fPool->unref();
}
bool SkPoolDiscardableMemory::lock() {
+ SkASSERT(!fLocked); // contract for SkDiscardableMemory
return fPool->lock(this);
}
void* SkPoolDiscardableMemory::data() {
- return fLocked ? fPointer : NULL;
+ SkASSERT(fLocked); // contract for SkDiscardableMemory
+ return fPointer;
}
void SkPoolDiscardableMemory::unlock() {
+ SkASSERT(fLocked); // contract for SkDiscardableMemory
fPool->unlock(this);
}
diff --git a/lazy/SkDiscardablePixelRef.cpp b/lazy/SkDiscardablePixelRef.cpp
index 6a9507c8..160ca5b4 100644
--- a/lazy/SkDiscardablePixelRef.cpp
+++ b/lazy/SkDiscardablePixelRef.cpp
@@ -9,19 +9,17 @@
#include "SkDiscardableMemory.h"
#include "SkImageGenerator.h"
-SkDiscardablePixelRef::SkDiscardablePixelRef(SkImageGenerator* generator,
- const SkImageInfo& info,
- size_t size,
+SkDiscardablePixelRef::SkDiscardablePixelRef(const SkImageInfo& info,
+ SkImageGenerator* generator,
size_t rowBytes,
SkDiscardableMemory::Factory* fact)
- : fGenerator(generator)
+ : INHERITED(info)
+ , fGenerator(generator)
, fDMFactory(fact)
- , fInfo(info)
- , fSize(size)
, fRowBytes(rowBytes)
- , fDiscardableMemory(NULL) {
+ , fDiscardableMemory(NULL)
+{
SkASSERT(fGenerator != NULL);
- SkASSERT(fSize > 0);
SkASSERT(fRowBytes > 0);
// The SkImageGenerator contract requires fGenerator to always
// decode the same image on each call to getPixels().
@@ -30,6 +28,9 @@ SkDiscardablePixelRef::SkDiscardablePixelRef(SkImageGenerator* generator,
}
SkDiscardablePixelRef::~SkDiscardablePixelRef() {
+ if (this->isLocked()) {
+ fDiscardableMemory->unlock();
+ }
SkDELETE(fDiscardableMemory);
SkSafeUnref(fDMFactory);
SkDELETE(fGenerator);
@@ -43,24 +44,28 @@ void* SkDiscardablePixelRef::onLockPixels(SkColorTable**) {
SkDELETE(fDiscardableMemory);
fDiscardableMemory = NULL;
}
+
+ const size_t size = this->info().getSafeSize(fRowBytes);
+
if (fDMFactory != NULL) {
- fDiscardableMemory = fDMFactory->create(fSize);
+ fDiscardableMemory = fDMFactory->create(size);
} else {
- fDiscardableMemory = SkDiscardableMemory::Create(fSize);
+ fDiscardableMemory = SkDiscardableMemory::Create(size);
}
if (NULL == fDiscardableMemory) {
return NULL; // Memory allocation failed.
}
void* pixels = fDiscardableMemory->data();
- if (!fGenerator->getPixels(fInfo, pixels, fRowBytes)) {
- return NULL; // TODO(halcanary) Find out correct thing to do.
+ if (!fGenerator->getPixels(this->info(), pixels, fRowBytes)) {
+ fDiscardableMemory->unlock();
+ SkDELETE(fDiscardableMemory);
+ fDiscardableMemory = NULL;
+ return NULL;
}
return pixels;
}
void SkDiscardablePixelRef::onUnlockPixels() {
- if (fDiscardableMemory != NULL) {
- fDiscardableMemory->unlock();
- }
+ fDiscardableMemory->unlock();
}
bool SkInstallDiscardablePixelRef(SkImageGenerator* generator,
@@ -80,10 +85,7 @@ bool SkInstallDiscardablePixelRef(SkImageGenerator* generator,
return dst->allocPixels(NULL, NULL);
}
SkAutoTUnref<SkDiscardablePixelRef> ref(SkNEW_ARGS(SkDiscardablePixelRef,
- (generator, info,
- dst->getSize(),
- dst->rowBytes(),
- factory)));
+ (info, generator, dst->rowBytes(), factory)));
dst->setPixelRef(ref);
return true;
}
diff --git a/lazy/SkDiscardablePixelRef.h b/lazy/SkDiscardablePixelRef.h
index 44c6df96..4b669383 100644
--- a/lazy/SkDiscardablePixelRef.h
+++ b/lazy/SkDiscardablePixelRef.h
@@ -30,8 +30,6 @@ protected:
private:
SkImageGenerator* const fGenerator;
SkDiscardableMemory::Factory* const fDMFactory;
- const SkImageInfo fInfo;
- const size_t fSize; // size of memory to be allocated
const size_t fRowBytes;
// These const members should not change over the life of the
// PixelRef, since the SkBitmap doesn't expect them to change.
@@ -39,9 +37,7 @@ private:
SkDiscardableMemory* fDiscardableMemory;
/* Takes ownership of SkImageGenerator. */
- SkDiscardablePixelRef(SkImageGenerator* generator,
- const SkImageInfo& info,
- size_t size,
+ SkDiscardablePixelRef(const SkImageInfo&, SkImageGenerator*,
size_t rowBytes,
SkDiscardableMemory::Factory* factory);
friend bool SkInstallDiscardablePixelRef(SkImageGenerator*,