blob: c26ca18041ffb9315e955a96a089ee996d34f2fd [file] [log] [blame]
senorblanco@chromium.org86fc2662013-05-31 17:49:12 +00001/*
2 * Copyright 2013 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 "SkXfermodeImageFilter.h"
9#include "SkCanvas.h"
10#include "SkColorPriv.h"
11#include "SkFlattenableBuffers.h"
12#include "SkXfermode.h"
13#if SK_SUPPORT_GPU
14#include "GrContext.h"
15#include "effects/GrSimpleTextureEffect.h"
16#include "SkGr.h"
17#include "SkImageFilterUtils.h"
18#endif
19
20///////////////////////////////////////////////////////////////////////////////
21
22SkXfermodeImageFilter::SkXfermodeImageFilter(SkXfermode* mode, SkImageFilter* background, SkImageFilter* foreground)
23 : INHERITED(background, foreground), fMode(mode) {
24 SkSafeRef(fMode);
25}
26
27SkXfermodeImageFilter::~SkXfermodeImageFilter() {
28 SkSafeUnref(fMode);
29}
30
31SkXfermodeImageFilter::SkXfermodeImageFilter(SkFlattenableReadBuffer& buffer)
32 : INHERITED(buffer) {
33 fMode = buffer.readFlattenableT<SkXfermode>();
34}
35
36void SkXfermodeImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
37 this->INHERITED::flatten(buffer);
38 buffer.writeFlattenable(fMode);
39}
40
41bool SkXfermodeImageFilter::onFilterImage(Proxy* proxy,
42 const SkBitmap& src,
43 const SkMatrix& ctm,
44 SkBitmap* dst,
45 SkIPoint* offset) {
46 SkBitmap background = src, foreground = src;
47 SkImageFilter* backgroundInput = getInput(0);
48 SkImageFilter* foregroundInput = getInput(1);
49 if (backgroundInput && !backgroundInput->filterImage(proxy, src, ctm, &background, offset)) {
50 return false;
51 }
52 if (foregroundInput && !foregroundInput->filterImage(proxy, src, ctm, &foreground, offset)) {
53 return false;
54 }
55 dst->setConfig(background.config(), background.width(), background.height());
56 dst->allocPixels();
57 SkCanvas canvas(*dst);
58 SkPaint paint;
59 paint.setXfermodeMode(SkXfermode::kSrc_Mode);
60 canvas.drawBitmap(background, 0, 0, &paint);
61 paint.setXfermode(fMode);
62 canvas.drawBitmap(foreground, 0, 0, &paint);
63 return true;
64}
65
66#if SK_SUPPORT_GPU
67
68bool SkXfermodeImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result) {
69 SkBitmap background;
70 if (!SkImageFilterUtils::GetInputResultGPU(getInput(0), proxy, src, &background)) {
71 return false;
72 }
commit-bot@chromium.orgb8d00db2013-06-26 19:18:23 +000073 GrTexture* backgroundTex = background.getTexture();
senorblanco@chromium.org86fc2662013-05-31 17:49:12 +000074 SkBitmap foreground;
75 if (!SkImageFilterUtils::GetInputResultGPU(getInput(1), proxy, src, &foreground)) {
76 return false;
77 }
commit-bot@chromium.orgb8d00db2013-06-26 19:18:23 +000078 GrTexture* foregroundTex = foreground.getTexture();
senorblanco@chromium.org86fc2662013-05-31 17:49:12 +000079 GrContext* context = foregroundTex->getContext();
80
81 GrEffectRef* xferEffect = NULL;
82
83 GrTextureDesc desc;
84 desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
85 desc.fWidth = src.width();
86 desc.fHeight = src.height();
87 desc.fConfig = kSkia8888_GrPixelConfig;
88
89 GrAutoScratchTexture ast(context, desc);
90 SkAutoTUnref<GrTexture> dst(ast.detach());
91
92 GrContext::AutoRenderTarget art(context, dst->asRenderTarget());
93
94 SkXfermode::Coeff sm, dm;
95 if (!SkXfermode::AsNewEffectOrCoeff(fMode, context, &xferEffect, &sm, &dm, backgroundTex)) {
96 return false;
97 }
98
99 GrPaint paint;
100 SkRect srcRect;
101 src.getBounds(&srcRect);
102 if (NULL != xferEffect) {
103 paint.colorStage(0)->setEffect(
104 GrSimpleTextureEffect::Create(foregroundTex, GrEffect::MakeDivByTextureWHMatrix(foregroundTex)))->unref();
commit-bot@chromium.orge904b452013-06-03 19:40:17 +0000105 paint.colorStage(1)->setEffect(xferEffect)->unref();
senorblanco@chromium.org86fc2662013-05-31 17:49:12 +0000106 context->drawRect(paint, srcRect);
107 } else {
108 paint.colorStage(0)->setEffect(
109 GrSimpleTextureEffect::Create(backgroundTex, GrEffect::MakeDivByTextureWHMatrix(backgroundTex)))->unref();
110 context->drawRect(paint, srcRect);
111 paint.setBlendFunc(sk_blend_to_grblend(sm), sk_blend_to_grblend(dm));
112 paint.colorStage(0)->setEffect(
113 GrSimpleTextureEffect::Create(foregroundTex, GrEffect::MakeDivByTextureWHMatrix(foregroundTex)))->unref();
114 context->drawRect(paint, srcRect);
115 }
116 return SkImageFilterUtils::WrapTexture(dst, src.width(), src.height(), result);
117}
118
119#endif