aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar senorblanco@chromium.org <senorblanco@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-10-10 20:36:13 +0000
committerGravatar senorblanco@chromium.org <senorblanco@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-10-10 20:36:13 +0000
commit9f25de79009ce721aa13abe71c38179d5a6710e2 (patch)
tree378ab68681b93697ca8351105e570fce4d39879e /src
parentefb1d77ad2cb77f6b124b0674fccf67d9b737b60 (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.cpp66
-rw-r--r--src/effects/SkBitmapSource.cpp4
-rw-r--r--src/effects/SkBlendImageFilter.cpp30
-rw-r--r--src/effects/SkMagnifierImageFilter.cpp3
-rw-r--r--src/effects/SkSingleInputImageFilter.cpp34
-rwxr-xr-xsrc/effects/SkTestImageFilters.cpp140
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;
}
}