| 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;
|
|
|