Index: src/lazy/SkCachingPixelRef.cpp |
diff --git a/src/lazy/SkCachingPixelRef.cpp b/src/lazy/SkCachingPixelRef.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..7cfb7525ea628f401fecbd76ee5646df9ccdcda3 |
--- /dev/null |
+++ b/src/lazy/SkCachingPixelRef.cpp |
@@ -0,0 +1,102 @@ |
+/* |
+ * Copyright 2013 Google Inc. |
+ * |
+ * Use of this source code is governed by a BSD-style license that can be |
+ * found in the LICENSE file. |
+ */ |
+ |
+#include "SkCachingPixelRef.h" |
+ |
+SkCachingPixelRef::SkCachingPixelRef(SkScaledImageCache* cache) |
+ : fErrorInDecoding(false) |
+ , fCache(cache) |
+ , fScaledCacheId(NULL) |
+ , fBitmapSize(SkISize::Make(0, 0)) { |
+ if (fCache == NULL) { |
scroggo
2013/10/31 21:53:06
NULL == fCache.
hal.canary
2013/11/01 03:29:24
Done.
|
+ fCache = SkScaledImageCache::Instance(); |
+ } |
+} |
+SkCachingPixelRef::~SkCachingPixelRef() { |
scroggo
2013/10/31 21:53:06
Maybe assert that fScaledCacheId is NULL?
hal.canary
2013/11/01 03:29:24
Done.
|
+} |
+ |
+bool SkCachingPixelRef::updateInfo() { |
+ if (fErrorInDecoding || !fBitmapSize.isZero()) { |
scroggo
2013/10/31 21:53:06
This block is painful for me to look at. I think i
hal.canary
2013/11/01 03:29:24
Done.
|
+ return !fErrorInDecoding; |
+ } |
+ if (!this->onDecodeInfo(&fBitmapSize, &fBitmapConfig, &fBitmapAlphaType)) { |
+ fErrorInDecoding = true; |
+ return false; |
+ } |
+ SkASSERT(!fBitmapSize.isZero()); |
+ return true; |
+} |
+ |
+bool SkCachingPixelRef::configure(SkBitmap* bitmap) { |
+ if (!this->updateInfo()) { |
+ return false; |
+ } |
+ return bitmap->setConfig(fBitmapConfig, fBitmapSize.width(), |
+ fBitmapSize.height(), 0, fBitmapAlphaType); |
+} |
+ |
+void* SkCachingPixelRef::onLockPixels(SkColorTable** colorTable) { |
+ (void)colorTable; |
+ if (!this->updateInfo()) { |
+ return NULL; |
+ } |
+ SkBitmap bitmap; |
+ |
+ fScaledCacheId = fCache->findAndLock(this->getGenerationID(), |
+ fBitmapSize.fWidth, |
+ fBitmapSize.fHeight, |
+ &bitmap); |
+ if (fScaledCacheId != NULL) { |
+ SkAutoLockPixels autoLockPixels(bitmap); |
+ void* pixels = bitmap.getPixels(); |
+ SkASSERT(NULL != pixels); |
+ // At this point, the autoLockPixels will unlockPixels() |
+ // to remove bitmap's lock on the pixels. We will then |
+ // destroy bitmap. The *only* guarantee that this pointer |
+ // remains valid is the guarantee made by |
+ // SkScaledImageCache that it will not destroy the *other* |
+ // bitmap (SkScaledImageCache::Rec.fBitmap) that holds a |
+ // reference to the concrete PixelRef while this record is |
+ // locked. |
+ return pixels; |
+ } else { |
+ // Cache has been purged, must re-decode. |
+ if (!this->onDecodeInto(0, &bitmap)) { |
+ return NULL; |
+ } |
+ SkAutoLockPixels autoLockPixels(bitmap); |
+ void* pixels = bitmap.getPixels(); |
+ SkASSERT(pixels != NULL); |
+ fScaledCacheId = fCache->addAndLock(this->getGenerationID(), |
+ fBitmapSize.fWidth, |
+ fBitmapSize.fHeight, |
+ bitmap); |
+ SkASSERT(fScaledCacheId != NULL); |
+ return pixels; |
scroggo
2013/10/31 21:53:06
Similar comment why pixels is still valid?
hal.canary
2013/11/01 03:29:24
I cleaned up the code to make this clear.
|
+ } |
+} |
+ |
+void SkCachingPixelRef::onUnlockPixels() { |
+ if (!fErrorInDecoding && (NULL != fScaledCacheId)) { |
scroggo
2013/10/31 21:53:06
If fErrorInDecoding is false, is it ever correct t
hal.canary
2013/11/01 03:29:24
I don't think so. Let me make this clear.
|
+ fCache->unlock(fScaledCacheId); |
+ fScaledCacheId = NULL; |
+ } |
+} |
+ |
+bool SkCachingPixelRef::onDecodeInto(int pow2, SkBitmap* bitmap) { |
+ SkBitmap tmp; |
+ if (!(this->configure(&tmp) && tmp.allocPixels(NULL, NULL))) { |
+ fErrorInDecoding = true; |
+ return false; |
+ } |
+ if (!this->onDecode(tmp.getPixels(), tmp.rowBytes())) { |
+ fErrorInDecoding = true; |
+ return false; |
+ } |
+ *bitmap = tmp; |
+ return true; |
+} |