Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2012 The Android Open Source Project
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "SkImageFilter.h"
      9 
     10 #include "SkBitmap.h"
     11 #include "SkFlattenableBuffers.h"
     12 #include "SkRect.h"
     13 #if SK_SUPPORT_GPU
     14 #include "GrContext.h"
     15 #include "GrTexture.h"
     16 #include "SkImageFilterUtils.h"
     17 #endif
     18 
     19 SK_DEFINE_INST_COUNT(SkImageFilter)
     20 
     21 SkImageFilter::SkImageFilter(int inputCount, SkImageFilter** inputs, const SkIRect* cropRect)
     22   : fInputCount(inputCount),
     23     fInputs(new SkImageFilter*[inputCount]),
     24     fCropRect(cropRect ? *cropRect : SkIRect::MakeLargest()) {
     25     for (int i = 0; i < inputCount; ++i) {
     26         fInputs[i] = inputs[i];
     27         SkSafeRef(fInputs[i]);
     28     }
     29 }
     30 
     31 SkImageFilter::SkImageFilter(SkImageFilter* input, const SkIRect* cropRect)
     32   : fInputCount(1),
     33     fInputs(new SkImageFilter*[1]),
     34     fCropRect(cropRect ? *cropRect : SkIRect::MakeLargest()) {
     35     fInputs[0] = input;
     36     SkSafeRef(fInputs[0]);
     37 }
     38 
     39 SkImageFilter::SkImageFilter(SkImageFilter* input1, SkImageFilter* input2, const SkIRect* cropRect)
     40   : fInputCount(2), fInputs(new SkImageFilter*[2]),
     41   fCropRect(cropRect ? *cropRect : SkIRect::MakeLargest()) {
     42     fInputs[0] = input1;
     43     fInputs[1] = input2;
     44     SkSafeRef(fInputs[0]);
     45     SkSafeRef(fInputs[1]);
     46 }
     47 
     48 SkImageFilter::~SkImageFilter() {
     49     for (int i = 0; i < fInputCount; i++) {
     50         SkSafeUnref(fInputs[i]);
     51     }
     52     delete[] fInputs;
     53 }
     54 
     55 SkImageFilter::SkImageFilter(SkFlattenableReadBuffer& buffer)
     56     : fInputCount(buffer.readInt()), fInputs(new SkImageFilter*[fInputCount]) {
     57     for (int i = 0; i < fInputCount; i++) {
     58         if (buffer.readBool()) {
     59             fInputs[i] = static_cast<SkImageFilter*>(buffer.readFlattenable());
     60         } else {
     61             fInputs[i] = NULL;
     62         }
     63     }
     64     buffer.readIRect(&fCropRect);
     65 }
     66 
     67 void SkImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
     68     buffer.writeInt(fInputCount);
     69     for (int i = 0; i < fInputCount; i++) {
     70         SkImageFilter* input = getInput(i);
     71         buffer.writeBool(input != NULL);
     72         if (input != NULL) {
     73             buffer.writeFlattenable(input);
     74         }
     75     }
     76     buffer.writeIRect(fCropRect);
     77 }
     78 
     79 bool SkImageFilter::filterImage(Proxy* proxy, const SkBitmap& src,
     80                                 const SkMatrix& ctm,
     81                                 SkBitmap* result, SkIPoint* loc) {
     82     SkASSERT(result);
     83     SkASSERT(loc);
     84     /*
     85      *  Give the proxy first shot at the filter. If it returns false, ask
     86      *  the filter to do it.
     87      */
     88     return (proxy && proxy->filterImage(this, src, ctm, result, loc)) ||
     89            this->onFilterImage(proxy, src, ctm, result, loc);
     90 }
     91 
     92 bool SkImageFilter::filterBounds(const SkIRect& src, const SkMatrix& ctm,
     93                                  SkIRect* dst) {
     94     SkASSERT(&src);
     95     SkASSERT(dst);
     96     return this->onFilterBounds(src, ctm, dst);
     97 }
     98 
     99 bool SkImageFilter::onFilterImage(Proxy*, const SkBitmap&, const SkMatrix&,
    100                                   SkBitmap*, SkIPoint*) {
    101     return false;
    102 }
    103 
    104 bool SkImageFilter::canFilterImageGPU() const {
    105     return this->asNewEffect(NULL, NULL, SkIPoint::Make(0, 0));
    106 }
    107 
    108 bool SkImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm,
    109                                    SkBitmap* result, SkIPoint* offset) {
    110 #if SK_SUPPORT_GPU
    111     SkBitmap input;
    112     SkASSERT(fInputCount == 1);
    113     if (!SkImageFilterUtils::GetInputResultGPU(this->getInput(0), proxy, src, ctm, &input, offset)) {
    114         return false;
    115     }
    116     GrTexture* srcTexture = input.getTexture();
    117     SkIRect bounds;
    118     src.getBounds(&bounds);
    119     if (!this->applyCropRect(&bounds)) {
    120         return false;
    121     }
    122     SkRect srcRect = SkRect::Make(bounds);
    123     SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
    124     GrContext* context = srcTexture->getContext();
    125 
    126     GrTextureDesc desc;
    127     desc.fFlags = kRenderTarget_GrTextureFlagBit,
    128     desc.fWidth = bounds.width();
    129     desc.fHeight = bounds.height();
    130     desc.fConfig = kRGBA_8888_GrPixelConfig;
    131 
    132     GrAutoScratchTexture dst(context, desc);
    133     GrContext::AutoMatrix am;
    134     am.setIdentity(context);
    135     GrContext::AutoRenderTarget art(context, dst.texture()->asRenderTarget());
    136     GrContext::AutoClip acs(context, dstRect);
    137     GrEffectRef* effect;
    138     this->asNewEffect(&effect, srcTexture, SkIPoint::Make(bounds.left(), bounds.top()));
    139     SkASSERT(effect);
    140     SkAutoUnref effectRef(effect);
    141     GrPaint paint;
    142     paint.addColorEffect(effect);
    143     context->drawRectToRect(paint, dstRect, srcRect);
    144 
    145     SkAutoTUnref<GrTexture> resultTex(dst.detach());
    146     SkImageFilterUtils::WrapTexture(resultTex, bounds.width(), bounds.height(), result);
    147     offset->fX += bounds.left();
    148     offset->fY += bounds.top();
    149     return true;
    150 #else
    151     return false;
    152 #endif
    153 }
    154 
    155 bool SkImageFilter::applyCropRect(SkIRect* rect) const {
    156     return rect->intersect(fCropRect);
    157 }
    158 
    159 bool SkImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
    160                                    SkIRect* dst) {
    161     *dst = src;
    162     return true;
    163 }
    164 
    165 bool SkImageFilter::asNewEffect(GrEffectRef**, GrTexture*, const SkIPoint& offset) const {
    166     return false;
    167 }
    168 
    169 bool SkImageFilter::asColorFilter(SkColorFilter**) const {
    170     return false;
    171 }
    172