diff options
author | senorblanco@chromium.org <senorblanco@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-10-10 20:36:13 +0000 |
---|---|---|
committer | senorblanco@chromium.org <senorblanco@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-10-10 20:36:13 +0000 |
commit | 9f25de79009ce721aa13abe71c38179d5a6710e2 (patch) | |
tree | 378ab68681b93697ca8351105e570fce4d39879e /src | |
parent | efb1d77ad2cb77f6b124b0674fccf67d9b737b60 (diff) |
This patch implements generalized DAG connectivity for SkImageFilter. SkImageFilter maintains a list of inputs, which can be constructed either from a SkImageFilter** or zero or more SkImageFilter* arguments (varargs).
Existing filters which maintained their own filter connectivity were refactored to use the new constructors and flattening/unflattening code. Modifying the remaining filters which are not yet DAG-friendly is left for future work; they are considered to have zero inputs for now.
Review URL: https://codereview.appspot.com/6443119
git-svn-id: http://skia.googlecode.com/svn/trunk@5891 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src')
-rw-r--r-- | src/core/SkImageFilter.cpp | 66 | ||||
-rw-r--r-- | src/effects/SkBitmapSource.cpp | 4 | ||||
-rw-r--r-- | src/effects/SkBlendImageFilter.cpp | 30 | ||||
-rw-r--r-- | src/effects/SkMagnifierImageFilter.cpp | 3 | ||||
-rw-r--r-- | src/effects/SkSingleInputImageFilter.cpp | 34 | ||||
-rwxr-xr-x | src/effects/SkTestImageFilters.cpp | 140 |
6 files changed, 143 insertions, 134 deletions
diff --git a/src/core/SkImageFilter.cpp b/src/core/SkImageFilter.cpp index bb31b79f04..573d49d1ef 100644 --- a/src/core/SkImageFilter.cpp +++ b/src/core/SkImageFilter.cpp @@ -6,10 +6,76 @@ */ #include "SkImageFilter.h" + +#include "SkBitmap.h" +#include "SkFlattenableBuffers.h" #include "SkRect.h" +#include "stdarg.h" SK_DEFINE_INST_COUNT(SkImageFilter) +SkImageFilter::SkImageFilter(int numInputs, SkImageFilter** inputs) + : fNumInputs(numInputs), fInputs(new SkImageFilter*[numInputs]) { + for (int i = 0; i < numInputs; ++i) { + fInputs[i] = inputs[i]; + SkSafeRef(fInputs[i]); + } +} + +SkImageFilter::SkImageFilter(int numInputs, ...) + : fNumInputs(numInputs), fInputs(new SkImageFilter*[numInputs]) { + va_list ap; + va_start(ap, numInputs); + for (int i = 0; i < numInputs; ++i) { + fInputs[i] = va_arg(ap, SkImageFilter*); + SkSafeRef(fInputs[i]); + } + va_end(ap); +} + +SkImageFilter::~SkImageFilter() { + for (int i = 0; i < fNumInputs; i++) { + SkSafeUnref(fInputs[i]); + } + delete[] fInputs; +} + +SkImageFilter::SkImageFilter(SkFlattenableReadBuffer& buffer) + : fNumInputs(buffer.readInt()), fInputs(new SkImageFilter*[fNumInputs]) { + for (int i = 0; i < fNumInputs; i++) { + if (buffer.readBool()) { + fInputs[i] = static_cast<SkImageFilter*>(buffer.readFlattenable()); + } else { + fInputs[i] = NULL; + } + } +} + +void SkImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const { + buffer.writeInt(fNumInputs); + for (int i = 0; i < fNumInputs; i++) { + SkImageFilter* input = getInput(i); + buffer.writeBool(input != NULL); + if (input != NULL) { + buffer.writeFlattenable(input); + } + } +} + +SkBitmap SkImageFilter::getInputResult(int index, Proxy* proxy, + const SkBitmap& src, const SkMatrix& ctm, + SkIPoint* loc) { + SkASSERT(index < fNumInputs); + SkImageFilter* input = getInput(index); + SkBitmap result; + if (input && input->filterImage(proxy, src, ctm, &result, loc)) { + return result; + } else { + return src; + } +} + + bool SkImageFilter::filterImage(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm, SkBitmap* result, SkIPoint* loc) { diff --git a/src/effects/SkBitmapSource.cpp b/src/effects/SkBitmapSource.cpp index 8aa0433bca..854df9df22 100644 --- a/src/effects/SkBitmapSource.cpp +++ b/src/effects/SkBitmapSource.cpp @@ -7,7 +7,9 @@ #include "SkBitmapSource.h" -SkBitmapSource::SkBitmapSource(const SkBitmap& bitmap) : fBitmap(bitmap) { +SkBitmapSource::SkBitmapSource(const SkBitmap& bitmap) + : INHERITED(0), + fBitmap(bitmap) { } SkBitmapSource::SkBitmapSource(SkFlattenableReadBuffer& buffer) diff --git a/src/effects/SkBlendImageFilter.cpp b/src/effects/SkBlendImageFilter.cpp index 1388e336dc..a1ad8ec1b4 100644 --- a/src/effects/SkBlendImageFilter.cpp +++ b/src/effects/SkBlendImageFilter.cpp @@ -52,38 +52,22 @@ SkPMColor multiply_proc(SkPMColor src, SkPMColor dst) { /////////////////////////////////////////////////////////////////////////////// SkBlendImageFilter::SkBlendImageFilter(SkBlendImageFilter::Mode mode, SkImageFilter* background, SkImageFilter* foreground) - : fMode(mode), fBackground(background), fForeground(foreground) + : INHERITED(2, background, foreground), fMode(mode) { - SkASSERT(NULL != background); - SkSafeRef(fBackground); - SkSafeRef(fForeground); } SkBlendImageFilter::~SkBlendImageFilter() { - SkSafeUnref(fBackground); - SkSafeUnref(fForeground); } SkBlendImageFilter::SkBlendImageFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) { fMode = (SkBlendImageFilter::Mode) buffer.readInt(); - fBackground = buffer.readFlattenableT<SkImageFilter>(); - if (buffer.readBool()) { - fForeground = buffer.readFlattenableT<SkImageFilter>(); - } else { - fForeground = NULL; - } } void SkBlendImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const { this->INHERITED::flatten(buffer); buffer.writeInt((int) fMode); - buffer.writeFlattenable(fBackground); - buffer.writeBool(NULL != fForeground); - if (NULL != fForeground) { - buffer.writeFlattenable(fForeground); - } } bool SkBlendImageFilter::onFilterImage(Proxy* proxy, @@ -92,11 +76,13 @@ bool SkBlendImageFilter::onFilterImage(Proxy* proxy, SkBitmap* dst, SkIPoint* offset) { SkBitmap background, foreground = src; - SkASSERT(NULL != fBackground); - if (!fBackground->filterImage(proxy, src, ctm, &background, offset)) { + SkImageFilter* backgroundInput = getBackgroundInput(); + SkImageFilter* foregroundInput = getForegroundInput(); + SkASSERT(NULL != backgroundInput); + if (!backgroundInput->filterImage(proxy, src, ctm, &background, offset)) { return false; } - if (fForeground && !fForeground->filterImage(proxy, src, ctm, &foreground, offset)) { + if (foregroundInput && !foregroundInput->filterImage(proxy, src, ctm, &foreground, offset)) { return false; } SkAutoLockPixels alp_foreground(foreground), alp_background(background); @@ -198,8 +184,8 @@ static GrTexture* getInputResultAsTexture(SkImageFilter::Proxy* proxy, } GrTexture* SkBlendImageFilter::onFilterImageGPU(Proxy* proxy, GrTexture* src, const SkRect& rect) { - SkAutoTUnref<GrTexture> background(getInputResultAsTexture(proxy, fBackground, src, rect)); - SkAutoTUnref<GrTexture> foreground(getInputResultAsTexture(proxy, fForeground, src, rect)); + SkAutoTUnref<GrTexture> background(getInputResultAsTexture(proxy, getBackgroundInput(), src, rect)); + SkAutoTUnref<GrTexture> foreground(getInputResultAsTexture(proxy, getForegroundInput(), src, rect)); GrContext* context = src->getContext(); GrTextureDesc desc; diff --git a/src/effects/SkMagnifierImageFilter.cpp b/src/effects/SkMagnifierImageFilter.cpp index cf64308249..9871fc0d21 100644 --- a/src/effects/SkMagnifierImageFilter.cpp +++ b/src/effects/SkMagnifierImageFilter.cpp @@ -241,8 +241,9 @@ SkMagnifierImageFilter::SkMagnifierImageFilter(SkFlattenableReadBuffer& buffer) fInset = buffer.readScalar(); } +// FIXME: implement single-input semantics SkMagnifierImageFilter::SkMagnifierImageFilter(SkRect srcRect, SkScalar inset) - : fSrcRect(srcRect), fInset(inset) { + : INHERITED(0), fSrcRect(srcRect), fInset(inset) { SkASSERT(srcRect.x() >= 0 && srcRect.y() >= 0 && inset >= 0); } diff --git a/src/effects/SkSingleInputImageFilter.cpp b/src/effects/SkSingleInputImageFilter.cpp index 3dd9ef9c90..2019e251e8 100644 --- a/src/effects/SkSingleInputImageFilter.cpp +++ b/src/effects/SkSingleInputImageFilter.cpp @@ -15,57 +15,45 @@ #include "SkGrPixelRef.h" #endif -SkSingleInputImageFilter::SkSingleInputImageFilter(SkImageFilter* input) : fInput(input) { - SkSafeRef(fInput); +SkSingleInputImageFilter::SkSingleInputImageFilter(SkImageFilter* input) : INHERITED(1, input) { } SkSingleInputImageFilter::~SkSingleInputImageFilter() { - SkSafeUnref(fInput); } -SkSingleInputImageFilter::SkSingleInputImageFilter(SkFlattenableReadBuffer& rb) { - if (rb.readBool()) { - fInput = rb.readFlattenableT<SkImageFilter>(); - } else { - fInput = NULL; - } +SkSingleInputImageFilter::SkSingleInputImageFilter(SkFlattenableReadBuffer& rb) + : INHERITED(rb) { } void SkSingleInputImageFilter::flatten(SkFlattenableWriteBuffer& wb) const { - wb.writeBool(NULL != fInput); - if (NULL != fInput) { - wb.writeFlattenable(fInput); - } + this->INHERITED::flatten(wb); } SkBitmap SkSingleInputImageFilter::getInputResult(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm, SkIPoint* offset) { - SkBitmap result; - if (fInput && fInput->filterImage(proxy, src, ctm, &result, offset)) { - return result; - } else { - return src; - } + return this->INHERITED::getInputResult(0, proxy, src, ctm, offset); } #if SK_SUPPORT_GPU +// FIXME: generalize and move to base class GrTexture* SkSingleInputImageFilter::getInputResultAsTexture(Proxy* proxy, GrTexture* src, const SkRect& rect) { GrTexture* resultTex = NULL; - if (!fInput) { + SkImageFilter* input = getInput(0); + if (!input) { resultTex = src; - } else if (fInput->canFilterImageGPU()) { + } else if (input->canFilterImageGPU()) { // onFilterImageGPU() already refs the result, so just return it here. - return fInput->onFilterImageGPU(proxy, src, rect); + return input->onFilterImageGPU(proxy, src, rect); } else { SkBitmap srcBitmap, result; srcBitmap.setConfig(SkBitmap::kARGB_8888_Config, src->width(), src->height()); srcBitmap.setPixelRef(new SkGrPixelRef(src))->unref(); SkIPoint offset; - if (fInput->filterImage(proxy, srcBitmap, SkMatrix(), &result, &offset)) { + if (input->filterImage(proxy, srcBitmap, SkMatrix(), &result, &offset)) { if (result.getTexture()) { resultTex = (GrTexture*) result.getTexture(); } else { diff --git a/src/effects/SkTestImageFilters.cpp b/src/effects/SkTestImageFilters.cpp index d28fda96ec..a51149d6a8 100755 --- a/src/effects/SkTestImageFilters.cpp +++ b/src/effects/SkTestImageFilters.cpp @@ -53,8 +53,6 @@ SkOffsetImageFilter::SkOffsetImageFilter(SkFlattenableReadBuffer& buffer) : INHE /////////////////////////////////////////////////////////////////////////////// SkComposeImageFilter::~SkComposeImageFilter() { - SkSafeUnref(fInner); - SkSafeUnref(fOuter); } bool SkComposeImageFilter::onFilterImage(Proxy* proxy, @@ -62,117 +60,102 @@ bool SkComposeImageFilter::onFilterImage(Proxy* proxy, const SkMatrix& ctm, SkBitmap* result, SkIPoint* loc) { - if (!fOuter && !fInner) { + SkImageFilter* outer = getInput(0); + SkImageFilter* inner = getInput(1); + + if (!outer && !inner) { return false; } - if (!fOuter || !fInner) { - return (fOuter ? fOuter : fInner)->filterImage(proxy, src, ctm, result, loc); + if (!outer || !inner) { + return (outer ? outer : inner)->filterImage(proxy, src, ctm, result, loc); } SkBitmap tmp; - return fInner->filterImage(proxy, src, ctm, &tmp, loc) && - fOuter->filterImage(proxy, tmp, ctm, result, loc); + return inner->filterImage(proxy, src, ctm, &tmp, loc) && + outer->filterImage(proxy, tmp, ctm, result, loc); } bool SkComposeImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm, SkIRect* dst) { - if (!fOuter && !fInner) { + SkImageFilter* outer = getInput(0); + SkImageFilter* inner = getInput(1); + + if (!outer && !inner) { return false; } - if (!fOuter || !fInner) { - return (fOuter ? fOuter : fInner)->filterBounds(src, ctm, dst); + if (!outer || !inner) { + return (outer ? outer : inner)->filterBounds(src, ctm, dst); } SkIRect tmp; - return fInner->filterBounds(src, ctm, &tmp) && - fOuter->filterBounds(tmp, ctm, dst); -} - -void SkComposeImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const { - this->INHERITED::flatten(buffer); - - buffer.writeFlattenable(fOuter); - buffer.writeFlattenable(fInner); + return inner->filterBounds(src, ctm, &tmp) && + outer->filterBounds(tmp, ctm, dst); } SkComposeImageFilter::SkComposeImageFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) { - fOuter = buffer.readFlattenableT<SkImageFilter>(); - fInner = buffer.readFlattenableT<SkImageFilter>(); } /////////////////////////////////////////////////////////////////////////////// -template <typename T> T* SkSafeRefReturn(T* obj) { - SkSafeRef(obj); - return obj; -} - -void SkMergeImageFilter::initAlloc(int count, bool hasModes) { - if (count < 1) { - fFilters = NULL; - fModes = NULL; - fCount = 0; - } else { - int modeCount = hasModes ? count : 0; - size_t size = sizeof(SkImageFilter*) * count + sizeof(uint8_t) * modeCount; +void SkMergeImageFilter::initAllocModes() { + if (numInputs()) { + size_t size = sizeof(uint8_t) * numInputs(); if (size <= sizeof(fStorage)) { - fFilters = SkTCast<SkImageFilter**>(fStorage); + fModes = SkTCast<uint8_t*>(fStorage); } else { - fFilters = SkTCast<SkImageFilter**>(sk_malloc_throw(size)); + fModes = SkTCast<uint8_t*>(sk_malloc_throw(size)); } - fModes = hasModes ? SkTCast<uint8_t*>(fFilters + count) : NULL; - fCount = count; + } else { + fModes = NULL; } } -void SkMergeImageFilter::init(SkImageFilter* const filters[], int count, - const SkXfermode::Mode modes[]) { - this->initAlloc(count, !!modes); - for (int i = 0; i < count; ++i) { - fFilters[i] = SkSafeRefReturn(filters[i]); - if (modes) { +void SkMergeImageFilter::initModes(const SkXfermode::Mode modes[]) { + if (modes) { + this->initAllocModes(); + for (int i = 0; i < numInputs(); ++i) { fModes[i] = SkToU8(modes[i]); } + } else { + fModes = NULL; } } SkMergeImageFilter::SkMergeImageFilter(SkImageFilter* first, SkImageFilter* second, - SkXfermode::Mode mode) { - SkImageFilter* filters[] = { first, second }; - SkXfermode::Mode modes[] = { mode, mode }; - this->init(filters, 2, SkXfermode::kSrcOver_Mode == mode ? NULL : modes); + SkXfermode::Mode mode) : INHERITED(2, first, second) { + if (SkXfermode::kSrcOver_Mode != mode) { + SkXfermode::Mode modes[] = { mode, mode }; + this->initModes(modes); + } else { + fModes = NULL; + } } SkMergeImageFilter::SkMergeImageFilter(SkImageFilter* const filters[], int count, - const SkXfermode::Mode modes[]) { - this->init(filters, count, modes); + const SkXfermode::Mode modes[]) : INHERITED(count, filters) { + this->initModes(modes); } SkMergeImageFilter::~SkMergeImageFilter() { - for (int i = 0; i < fCount; ++i) { - SkSafeUnref(fFilters[i]); - } - if (fFilters != SkTCast<SkImageFilter**>(fStorage)) { - sk_free(fFilters); - // fModes is allocated in the same block as fFilters, so no need to - // separately free it. + if (fModes != SkTCast<uint8_t*>(fStorage)) { + sk_free(fModes); } } bool SkMergeImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm, SkIRect* dst) { - if (fCount < 1) { + if (numInputs() < 1) { return false; } SkIRect totalBounds; - for (int i = 0; i < fCount; ++i) { - SkImageFilter* filter = fFilters[i]; + for (int i = 0; i < numInputs(); ++i) { + SkImageFilter* filter = getInput(i); SkIRect r; if (filter) { if (!filter->filterBounds(src, ctm, &r)) { @@ -197,7 +180,7 @@ bool SkMergeImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm, bool SkMergeImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm, SkBitmap* result, SkIPoint* loc) { - if (fCount < 1) { + if (numInputs() < 1) { return false; } @@ -218,11 +201,11 @@ bool SkMergeImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src, OwnDeviceCanvas canvas(dst); SkPaint paint; - for (int i = 0; i < fCount; ++i) { + for (int i = 0; i < numInputs(); ++i) { SkBitmap tmp; const SkBitmap* srcPtr; SkIPoint pos = *loc; - SkImageFilter* filter = fFilters[i]; + SkImageFilter* filter = getInput(i); if (filter) { if (!filter->filterImage(proxy, src, ctm, &tmp, &pos)) { return false; @@ -248,37 +231,20 @@ bool SkMergeImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src, void SkMergeImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const { this->INHERITED::flatten(buffer); - int storedCount = fCount; + buffer.writeBool(fModes != NULL); if (fModes) { - // negative count signals we have modes - storedCount = -storedCount; - } - buffer.writeInt(storedCount); - - if (fCount) { - for (int i = 0; i < fCount; ++i) { - buffer.writeFlattenable(fFilters[i]); - } - if (fModes) { - buffer.writeByteArray(fModes, fCount * sizeof(fModes[0])); - } + buffer.writeByteArray(fModes, numInputs() * sizeof(fModes[0])); } } SkMergeImageFilter::SkMergeImageFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) { - int storedCount = buffer.readInt(); - this->initAlloc(SkAbs32(storedCount), storedCount < 0); - - for (int i = 0; i < fCount; ++i) { - fFilters[i] = buffer.readFlattenableT<SkImageFilter>(); - } - - if (fModes) { - SkASSERT(storedCount < 0); - SkASSERT(buffer.getArrayCount() == fCount * sizeof(fModes[0])); + bool hasModes = buffer.readBool(); + if (hasModes) { + this->initAllocModes(); + SkASSERT(buffer.getArrayCount() == numInputs() * sizeof(fModes[0])); buffer.readByteArray(fModes); } else { - SkASSERT(storedCount >= 0); + fModes = 0; } } |