1/* 2 * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> 3 * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> 4 * Copyright (C) 2005 Eric Seidel <eric@webkit.org> 5 * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> 6 * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies) 7 * Copyright (C) 2013 Google Inc. All rights reserved. 8 * 9 * This library is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU Library General Public 11 * License as published by the Free Software Foundation; either 12 * version 2 of the License, or (at your option) any later version. 13 * 14 * This library is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 * Library General Public License for more details. 18 * 19 * You should have received a copy of the GNU Library General Public License 20 * along with this library; see the file COPYING.LIB. If not, write to 21 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 22 * Boston, MA 02110-1301, USA. 23 */ 24 25#include "config.h" 26#include "platform/graphics/filters/FEBlend.h" 27 28#include "SkBitmapSource.h" 29#include "SkXfermodeImageFilter.h" 30#include "platform/graphics/GraphicsContext.h" 31#include "platform/graphics/cpu/arm/filters/FEBlendNEON.h" 32#include "platform/graphics/filters/SkiaImageFilterBuilder.h" 33#include "platform/graphics/skia/NativeImageSkia.h" 34#include "platform/graphics/skia/SkiaUtils.h" 35#include "platform/text/TextStream.h" 36#include "wtf/Uint8ClampedArray.h" 37 38typedef unsigned char (*BlendType)(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char alphaB); 39 40namespace blink { 41 42FEBlend::FEBlend(Filter* filter, WebBlendMode mode) 43 : FilterEffect(filter) 44 , m_mode(mode) 45{ 46} 47 48PassRefPtr<FEBlend> FEBlend::create(Filter* filter, WebBlendMode mode) 49{ 50 return adoptRef(new FEBlend(filter, mode)); 51} 52 53WebBlendMode FEBlend::blendMode() const 54{ 55 return m_mode; 56} 57 58bool FEBlend::setBlendMode(WebBlendMode mode) 59{ 60 if (m_mode == mode) 61 return false; 62 m_mode = mode; 63 return true; 64} 65 66#if HAVE(ARM_NEON_INTRINSICS) 67bool FEBlend::applySoftwareNEON() 68{ 69 if (m_mode != WebBlendModeNormal 70 && m_mode != WebBlendModeMultiply 71 && m_mode != WebBlendModeScreen 72 && m_mode != WebBlendModeDarken 73 && m_mode != WebBlendModeLighten) 74 return false; 75 76 Uint8ClampedArray* dstPixelArray = createPremultipliedImageResult(); 77 if (!dstPixelArray) 78 return true; 79 80 FilterEffect* in = inputEffect(0); 81 FilterEffect* in2 = inputEffect(1); 82 83 IntRect effectADrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect()); 84 RefPtr<Uint8ClampedArray> srcPixelArrayA = in->asPremultipliedImage(effectADrawingRect); 85 86 IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->absolutePaintRect()); 87 RefPtr<Uint8ClampedArray> srcPixelArrayB = in2->asPremultipliedImage(effectBDrawingRect); 88 89 unsigned pixelArrayLength = srcPixelArrayA->length(); 90 ASSERT(pixelArrayLength == srcPixelArrayB->length()); 91 92 if (pixelArrayLength >= 8) { 93 platformApplyNEON(srcPixelArrayA->data(), srcPixelArrayB->data(), dstPixelArray->data(), pixelArrayLength); 94 } else { 95 // If there is just one pixel we expand it to two. 96 ASSERT(pixelArrayLength > 0); 97 uint32_t sourceA[2] = {0, 0}; 98 uint32_t sourceBAndDest[2] = {0, 0}; 99 100 sourceA[0] = reinterpret_cast<uint32_t*>(srcPixelArrayA->data())[0]; 101 sourceBAndDest[0] = reinterpret_cast<uint32_t*>(srcPixelArrayB->data())[0]; 102 platformApplyNEON(reinterpret_cast<uint8_t*>(sourceA), reinterpret_cast<uint8_t*>(sourceBAndDest), reinterpret_cast<uint8_t*>(sourceBAndDest), 8); 103 reinterpret_cast<uint32_t*>(dstPixelArray->data())[0] = sourceBAndDest[0]; 104 } 105 return true; 106} 107#endif 108 109void FEBlend::applySoftware() 110{ 111#if HAVE(ARM_NEON_INTRINSICS) 112 if (applySoftwareNEON()) 113 return; 114#endif 115 116 FilterEffect* in = inputEffect(0); 117 FilterEffect* in2 = inputEffect(1); 118 119 ImageBuffer* resultImage = createImageBufferResult(); 120 if (!resultImage) 121 return; 122 GraphicsContext* filterContext = resultImage->context(); 123 124 ImageBuffer* imageBuffer = in->asImageBuffer(); 125 ImageBuffer* imageBuffer2 = in2->asImageBuffer(); 126 ASSERT(imageBuffer); 127 ASSERT(imageBuffer2); 128 129 filterContext->drawImageBuffer(imageBuffer2, drawingRegionOfInputImage(in2->absolutePaintRect())); 130 filterContext->drawImageBuffer(imageBuffer, drawingRegionOfInputImage(in->absolutePaintRect()), 0, CompositeSourceOver, m_mode); 131} 132 133PassRefPtr<SkImageFilter> FEBlend::createImageFilter(SkiaImageFilterBuilder* builder) 134{ 135 RefPtr<SkImageFilter> foreground(builder->build(inputEffect(0), operatingColorSpace())); 136 RefPtr<SkImageFilter> background(builder->build(inputEffect(1), operatingColorSpace())); 137 RefPtr<SkXfermode> mode(adoptRef(SkXfermode::Create(WebCoreCompositeToSkiaComposite(CompositeSourceOver, m_mode)))); 138 SkImageFilter::CropRect cropRect = getCropRect(builder->cropOffset()); 139 return adoptRef(SkXfermodeImageFilter::Create(mode.get(), background.get(), foreground.get(), &cropRect)); 140} 141 142TextStream& FEBlend::externalRepresentation(TextStream& ts, int indent) const 143{ 144 writeIndent(ts, indent); 145 ts << "[feBlend"; 146 FilterEffect::externalRepresentation(ts); 147 ts << " mode=\"" << (m_mode == WebBlendModeNormal ? "normal" : compositeOperatorName(CompositeSourceOver, m_mode)) << "\"]\n"; 148 inputEffect(0)->externalRepresentation(ts, indent + 1); 149 inputEffect(1)->externalRepresentation(ts, indent + 1); 150 return ts; 151} 152 153} // namespace blink 154