Index: src/core/SkImageFilter.cpp |
diff --git a/src/core/SkImageFilter.cpp b/src/core/SkImageFilter.cpp |
index fd98911ca58c705e01c11803976d66b403979d01..cde77381091107c065aea53d11f243cce3fb6163 100644 |
--- a/src/core/SkImageFilter.cpp |
+++ b/src/core/SkImageFilter.cpp |
@@ -10,11 +10,15 @@ |
#include "SkBitmap.h" |
#include "SkChecksum.h" |
#include "SkDevice.h" |
+#include "SkImage.h" |
+#include "SkImagePriv.h" |
+#include "SkImage_Base.h" |
#include "SkLazyPtr.h" |
#include "SkMatrixImageFilter.h" |
#include "SkReadBuffer.h" |
#include "SkWriteBuffer.h" |
#include "SkRect.h" |
+#include "SkSurface.h" |
#include "SkTDynamicHash.h" |
#include "SkTInternalLList.h" |
#include "SkValidationUtils.h" |
@@ -165,13 +169,12 @@ void SkImageFilter::flatten(SkWriteBuffer& buffer) const { |
buffer.writeUInt(fCropRect.flags()); |
} |
-bool SkImageFilter::filterImage(Proxy* proxy, const SkBitmap& src, |
+bool SkImageFilter::filterImage(Proxy* proxy, const SkImage* src, |
const Context& context, |
- SkBitmap* result, SkIPoint* offset) const { |
- SkASSERT(result); |
+ SkAutoTUnref<const SkImage>& result, SkIPoint* offset) const { |
SkASSERT(offset); |
- uint32_t srcGenID = fUsesSrcInput ? src.getGenerationID() : 0; |
- Cache::Key key(fUniqueID, context.ctm(), context.clipBounds(), srcGenID); |
+ uint32_t srcUniqueID = fUsesSrcInput ? src->uniqueID() : 0; |
+ Cache::Key key(fUniqueID, context.ctm(), context.clipBounds(), srcUniqueID); |
if (context.cache()) { |
if (context.cache()->get(key, result, offset)) { |
return true; |
@@ -182,9 +185,10 @@ bool SkImageFilter::filterImage(Proxy* proxy, const SkBitmap& src, |
* the filter to do it. |
*/ |
if ((proxy && proxy->filterImage(this, src, context, result, offset)) || |
- this->onFilterImage(proxy, src, context, result, offset)) { |
+ (this->onFilterImage(proxy, src, context, result, offset))) { |
+ SkASSERT(result); |
if (context.cache()) { |
- context.cache()->set(key, *result, *offset); |
+ context.cache()->set(key, result, *offset); |
} |
return true; |
} |
@@ -220,8 +224,8 @@ void SkImageFilter::computeFastBounds(const SkRect& src, SkRect* dst) const { |
} |
} |
-bool SkImageFilter::onFilterImage(Proxy*, const SkBitmap&, const Context&, |
- SkBitmap*, SkIPoint*) const { |
+bool SkImageFilter::onFilterImage(Proxy*, const SkImage*, const Context&, |
+ SkAutoTUnref<const SkImage>&, SkIPoint*) const { |
return false; |
} |
@@ -229,21 +233,27 @@ bool SkImageFilter::canFilterImageGPU() const { |
return this->asFragmentProcessor(NULL, NULL, SkMatrix::I(), SkIRect()); |
} |
-bool SkImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const Context& ctx, |
- SkBitmap* result, SkIPoint* offset) const { |
+bool SkImageFilter::filterImageGPU(Proxy* proxy, const SkImage* src, const Context& ctx, |
+ SkAutoTUnref<const SkImage>& result, SkIPoint* offset) const { |
#if SK_SUPPORT_GPU |
- SkBitmap input = src; |
- SkASSERT(fInputCount == 1); |
+ SkAutoTUnref<const SkImage> filtered(SkRef(src)); |
SkIPoint srcOffset = SkIPoint::Make(0, 0); |
+ |
+ SkASSERT(fInputCount == 1); |
if (this->getInput(0) && |
- !this->getInput(0)->getInputResultGPU(proxy, src, ctx, &input, &srcOffset)) { |
+ !this->getInput(0)->getInputResultGPU(proxy, src, ctx, filtered, &srcOffset)) { |
return false; |
} |
- GrTexture* srcTexture = input.getTexture(); |
+ |
+ SkAutoTUnref<const SkImage> cropped; |
SkIRect bounds; |
- if (!this->applyCropRect(ctx, proxy, input, &srcOffset, &bounds, &input)) { |
+ if (!this->applyCropRect(ctx, proxy, filtered, &srcOffset, &bounds, cropped)) { |
return false; |
} |
+ filtered.reset(NULL); |
+ |
+ GrTexture* srcTexture = cropped->getTexture(); |
+ |
SkRect srcRect = SkRect::Make(bounds); |
SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height()); |
GrContext* context = srcTexture->getContext(); |
@@ -276,17 +286,19 @@ bool SkImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const Cont |
context->drawNonAARectToRect(dst->asRenderTarget(), clip, paint, SkMatrix::I(), dstRect, |
srcRect); |
- WrapTexture(dst, bounds.width(), bounds.height(), result); |
+ if (!WrapTexture(dst, bounds.width(), bounds.height(), result)) { |
+ return false; |
+ } |
return true; |
} |
#endif |
return false; |
} |
-bool SkImageFilter::applyCropRect(const Context& ctx, const SkBitmap& src, |
+bool SkImageFilter::applyCropRect(const Context& ctx, const SkImage* src, |
const SkIPoint& srcOffset, SkIRect* bounds) const { |
- SkIRect srcBounds; |
- src.getBounds(&srcBounds); |
+ SkIRect srcBounds = NULL == src ? SkIRect::MakeEmpty() |
+ : SkIRect::MakeWH(src->width(), src->height()); |
srcBounds.offset(srcOffset); |
SkRect cropRect; |
ctx.ctm().mapRect(&cropRect, fCropRect.rect()); |
@@ -303,10 +315,11 @@ bool SkImageFilter::applyCropRect(const Context& ctx, const SkBitmap& src, |
return true; |
} |
-bool SkImageFilter::applyCropRect(const Context& ctx, Proxy* proxy, const SkBitmap& src, |
- SkIPoint* srcOffset, SkIRect* bounds, SkBitmap* dst) const { |
- SkIRect srcBounds; |
- src.getBounds(&srcBounds); |
+bool SkImageFilter::applyCropRect(const Context& ctx, Proxy* proxy, const SkImage* src, |
+ SkIPoint* srcOffset, SkIRect* bounds, |
+ SkAutoTUnref<const SkImage>& dst) const { |
+ SkASSERT(src); |
+ SkIRect srcBounds = SkIRect::MakeWH(src->width(), src->height()); |
srcBounds.offset(*srcOffset); |
SkRect cropRect; |
ctx.ctm().mapRect(&cropRect, fCropRect.rect()); |
@@ -321,7 +334,7 @@ bool SkImageFilter::applyCropRect(const Context& ctx, Proxy* proxy, const SkBitm |
return false; |
} |
if (srcBounds.contains(*bounds)) { |
- *dst = src; |
+ dst.reset(SkRef(src)); |
return true; |
} else { |
SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds->width(), bounds->height())); |
@@ -330,9 +343,13 @@ bool SkImageFilter::applyCropRect(const Context& ctx, Proxy* proxy, const SkBitm |
} |
SkCanvas canvas(device); |
canvas.clear(0x00000000); |
- canvas.drawBitmap(src, srcOffset->x() - bounds->x(), srcOffset->y() - bounds->y()); |
+ canvas.drawImage(src, srcOffset->x() - bounds->x(), srcOffset->y() - bounds->y()); |
*srcOffset = SkIPoint::Make(bounds->x(), bounds->y()); |
- *dst = device->accessBitmap(false); |
+ SkImage* image = device->newImageSnapshot(); |
+ if (NULL == image) { |
+ return false; |
+ } |
+ dst.reset(image); |
return true; |
} |
} |
@@ -377,31 +394,45 @@ SkImageFilter* SkImageFilter::CreateMatrixFilter(const SkMatrix& matrix, |
#if SK_SUPPORT_GPU |
-void SkImageFilter::WrapTexture(GrTexture* texture, int width, int height, SkBitmap* result) { |
+bool SkImageFilter::WrapTexture(GrTexture* texture, int width, int height, |
+ SkAutoTUnref<const SkImage>& result) { |
+ // TODO: currently we go texture->bitmap->surface, when we should go rendertarget->device. |
+ SkBitmap bitmap; |
SkImageInfo info = SkImageInfo::MakeN32Premul(width, height); |
- result->setInfo(info); |
- result->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, texture)))->unref(); |
+ bitmap.setInfo(info); |
+ bitmap.setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, texture)))->unref(); |
+ SkImage* image = SkNewImageFromBitmapTexture(bitmap, texture->desc().fSampleCnt, |
+ SkSurface::kYes_Budgeted); |
+ if (NULL == image) { |
+ return false; |
+ } |
+ result.reset(image); |
+ return true; |
} |
bool SkImageFilter::getInputResultGPU(SkImageFilter::Proxy* proxy, |
- const SkBitmap& src, const Context& ctx, |
- SkBitmap* result, SkIPoint* offset) const { |
+ const SkImage* src, const Context& ctx, |
+ SkAutoTUnref<const SkImage>& result, SkIPoint* offset) const { |
// Ensure that GrContext calls under filterImage and filterImageGPU below will see an identity |
// matrix with no clip and that the matrix, clip, and render target set before this function was |
// called are restored before we return to the caller. |
- GrContext* context = src.getTexture()->getContext(); |
- |
+ GrContext* context = src->getTexture()->getContext(); |
if (this->canFilterImageGPU()) { |
return this->filterImageGPU(proxy, src, ctx, result, offset); |
} else { |
if (this->filterImage(proxy, src, ctx, result, offset)) { |
if (!result->getTexture()) { |
- const SkImageInfo info = result->info(); |
- if (kUnknown_SkColorType == info.colorType()) { |
+ SkBitmap bitmap; |
+ if (!as_IB(result)->getROPixels(&bitmap)) { |
+ return false; |
+ } |
+ if (kUnknown_SkColorType == bitmap.colorType()) { |
+ return false; |
+ } |
+ SkAutoTUnref<GrTexture> resultTex(GrRefCachedBitmapTexture(context, bitmap, NULL)); |
+ if (!WrapTexture(resultTex, bitmap.width(), bitmap.height(), result)) { |
return false; |
} |
- SkAutoTUnref<GrTexture> resultTex(GrRefCachedBitmapTexture(context, *result, NULL)); |
- result->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, resultTex)))->unref(); |
} |
return true; |
} else { |
@@ -427,10 +458,10 @@ public: |
} |
} |
struct Value { |
- Value(const Key& key, const SkBitmap& bitmap, const SkIPoint& offset) |
- : fKey(key), fBitmap(bitmap), fOffset(offset) {} |
+ Value(const Key& key, const SkImage* value, const SkIPoint& offset) |
+ : fKey(key), fImage(SkRef(value)), fOffset(offset) {} |
Key fKey; |
- SkBitmap fBitmap; |
+ SkAutoTUnref<const SkImage> fImage; |
SkIPoint fOffset; |
static const Key& GetKey(const Value& v) { |
return v.fKey; |
@@ -440,10 +471,10 @@ public: |
} |
SK_DECLARE_INTERNAL_LLIST_INTERFACE(Value); |
}; |
- bool get(const Key& key, SkBitmap* result, SkIPoint* offset) const SK_OVERRIDE { |
+ bool get(const Key& key, SkAutoTUnref<const SkImage>& result, SkIPoint* offset) const SK_OVERRIDE { |
SkAutoMutexAcquire mutex(fMutex); |
if (Value* v = fLookup.find(key)) { |
- *result = v->fBitmap; |
+ result.reset(SkRef(v->fImage.get())); |
*offset = v->fOffset; |
if (v != fLRU.head()) { |
fLRU.remove(v); |
@@ -453,15 +484,15 @@ public: |
} |
return false; |
} |
- void set(const Key& key, const SkBitmap& result, const SkIPoint& offset) SK_OVERRIDE { |
+ void set(const Key& key, const SkImage* image, const SkIPoint& offset) SK_OVERRIDE { |
SkAutoMutexAcquire mutex(fMutex); |
if (Value* v = fLookup.find(key)) { |
removeInternal(v); |
} |
- Value* v = new Value(key, result, offset); |
+ Value* v = new Value(key, image, offset); |
fLookup.add(v); |
fLRU.addToHead(v); |
- fCurrentBytes += result.getSize(); |
+ fCurrentBytes += as_IB(image)->getSize(); |
while (fCurrentBytes > fMaxBytes) { |
Value* tail = fLRU.tail(); |
SkASSERT(tail); |
@@ -473,7 +504,7 @@ public: |
} |
private: |
void removeInternal(Value* v) { |
- fCurrentBytes -= v->fBitmap.getSize(); |
+ fCurrentBytes -= as_IB(v->fImage)->getSize(); |
fLRU.remove(v); |
fLookup.remove(v->fKey); |
delete v; |