Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(592)

Side by Side Diff: Source/platform/graphics/filters/FEBlend.cpp

Issue 416093002: Use GraphicContext::drawImageBuffer in FEBlend (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Some rebaselines. Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> 2 * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org>
3 * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> 3 * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org>
4 * Copyright (C) 2005 Eric Seidel <eric@webkit.org> 4 * Copyright (C) 2005 Eric Seidel <eric@webkit.org>
5 * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> 5 * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
6 * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies) 6 * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
7 * Copyright (C) 2013 Google Inc. All rights reserved. 7 * Copyright (C) 2013 Google Inc. All rights reserved.
8 * 8 *
9 * This library is free software; you can redistribute it and/or 9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public 10 * modify it under the terms of the GNU Library General Public
(...skipping 13 matching lines...) Expand all
24 24
25 #include "config.h" 25 #include "config.h"
26 #include "platform/graphics/filters/FEBlend.h" 26 #include "platform/graphics/filters/FEBlend.h"
27 27
28 #include "SkBitmapSource.h" 28 #include "SkBitmapSource.h"
29 #include "SkXfermodeImageFilter.h" 29 #include "SkXfermodeImageFilter.h"
30 #include "platform/graphics/GraphicsContext.h" 30 #include "platform/graphics/GraphicsContext.h"
31 #include "platform/graphics/cpu/arm/filters/FEBlendNEON.h" 31 #include "platform/graphics/cpu/arm/filters/FEBlendNEON.h"
32 #include "platform/graphics/filters/SkiaImageFilterBuilder.h" 32 #include "platform/graphics/filters/SkiaImageFilterBuilder.h"
33 #include "platform/graphics/skia/NativeImageSkia.h" 33 #include "platform/graphics/skia/NativeImageSkia.h"
34 #include "platform/graphics/skia/SkiaUtils.h"
34 #include "platform/text/TextStream.h" 35 #include "platform/text/TextStream.h"
35 #include "wtf/Uint8ClampedArray.h" 36 #include "wtf/Uint8ClampedArray.h"
36 37
37 typedef unsigned char (*BlendType)(unsigned char colorA, unsigned char colorB, u nsigned char alphaA, unsigned char alphaB); 38 typedef unsigned char (*BlendType)(unsigned char colorA, unsigned char colorB, u nsigned char alphaA, unsigned char alphaB);
38 39
39 namespace blink { 40 namespace blink {
40 41
41 FEBlend::FEBlend(Filter* filter, BlendModeType mode) 42 FEBlend::FEBlend(Filter* filter, BlendModeType mode)
42 : FilterEffect(filter) 43 : FilterEffect(filter)
43 , m_mode(mode) 44 , m_mode(mode)
(...skipping 11 matching lines...) Expand all
55 } 56 }
56 57
57 bool FEBlend::setBlendMode(BlendModeType mode) 58 bool FEBlend::setBlendMode(BlendModeType mode)
58 { 59 {
59 if (m_mode == mode) 60 if (m_mode == mode)
60 return false; 61 return false;
61 m_mode = mode; 62 m_mode = mode;
62 return true; 63 return true;
63 } 64 }
64 65
65 static inline unsigned char fastDivideBy255(uint16_t value) 66 static WebBlendMode toWebBlendMode(BlendModeType mode)
66 { 67 {
67 // This is an approximate algorithm for division by 255, but it gives accura te results for 16bit values. 68 switch (mode) {
68 uint16_t quotient = value >> 8; 69 case FEBLEND_MODE_NORMAL:
69 uint16_t remainder = value - (quotient * 255) + 1; 70 return WebBlendModeNormal;
70 return quotient + (remainder >> 8); 71 case FEBLEND_MODE_MULTIPLY:
71 } 72 return WebBlendModeMultiply;
72 73 case FEBLEND_MODE_SCREEN:
73 inline unsigned char feBlendNormal(unsigned char colorA, unsigned char colorB, u nsigned char alphaA, unsigned char) 74 return WebBlendModeScreen;
74 { 75 case FEBLEND_MODE_DARKEN:
75 return fastDivideBy255((255 - alphaA) * colorB + colorA * 255); 76 return WebBlendModeDarken;
76 } 77 case FEBLEND_MODE_LIGHTEN:
77 78 return WebBlendModeLighten;
78 inline unsigned char feBlendMultiply(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char alphaB) 79 default:
79 { 80 return WebBlendModeNormal;
f(malita) 2014/07/24 16:23:49 ASSERT_NOT_REACHED()?
fs 2014/07/25 10:52:00 Added.
80 return fastDivideBy255((255 - alphaA) * colorB + (255 - alphaB + colorB) * c olorA);
81 }
82
83 inline unsigned char feBlendScreen(unsigned char colorA, unsigned char colorB, u nsigned char, unsigned char)
84 {
85 return fastDivideBy255((colorB + colorA) * 255 - colorA * colorB);
86 }
87
88 inline unsigned char feBlendDarken(unsigned char colorA, unsigned char colorB, u nsigned char alphaA, unsigned char alphaB)
89 {
90 return fastDivideBy255(std::min((255 - alphaA) * colorB + colorA * 255, (255 - alphaB) * colorA + colorB * 255));
91 }
92
93 inline unsigned char feBlendLighten(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char alphaB)
94 {
95 return fastDivideBy255(std::max((255 - alphaA) * colorB + colorA * 255, (255 - alphaB) * colorA + colorB * 255));
96 }
97
98 inline unsigned char feBlendUnknown(unsigned char, unsigned char, unsigned char, unsigned char)
99 {
100 return 0;
101 }
102
103 template<BlendType BlendFunction>
104 static void platformApply(unsigned char* sourcePixelA, unsigned char* sourcePixe lB,
105 unsigned char* destinationPixel, unsigned pixelArrayLe ngth)
106 {
107 unsigned len = pixelArrayLength / 4;
108 for (unsigned pixelOffset = 0; pixelOffset < len; pixelOffset++) {
109 unsigned char alphaA = sourcePixelA[3];
110 unsigned char alphaB = sourcePixelB[3];
111 destinationPixel[0] = BlendFunction(sourcePixelA[0], sourcePixelB[0], al phaA, alphaB);
112 destinationPixel[1] = BlendFunction(sourcePixelA[1], sourcePixelB[1], al phaA, alphaB);
113 destinationPixel[2] = BlendFunction(sourcePixelA[2], sourcePixelB[2], al phaA, alphaB);
114 destinationPixel[3] = 255 - fastDivideBy255((255 - alphaA) * (255 - alph aB));
115 sourcePixelA += 4;
116 sourcePixelB += 4;
117 destinationPixel += 4;
118 } 81 }
119 } 82 }
120 83
121 void FEBlend::platformApplyGeneric(unsigned char* sourcePixelA, unsigned char* s ourcePixelB,
122 unsigned char* destinationPixel, unsigned pix elArrayLength)
123 {
124 switch (m_mode) {
125 case FEBLEND_MODE_NORMAL:
126 platformApply<feBlendNormal>(sourcePixelA, sourcePixelB, destinationPixe l, pixelArrayLength);
127 break;
128 case FEBLEND_MODE_MULTIPLY:
129 platformApply<feBlendMultiply>(sourcePixelA, sourcePixelB, destinationPi xel, pixelArrayLength);
130 break;
131 case FEBLEND_MODE_SCREEN:
132 platformApply<feBlendScreen>(sourcePixelA, sourcePixelB, destinationPixe l, pixelArrayLength);
133 break;
134 case FEBLEND_MODE_DARKEN:
135 platformApply<feBlendDarken>(sourcePixelA, sourcePixelB, destinationPixe l, pixelArrayLength);
136 break;
137 case FEBLEND_MODE_LIGHTEN:
138 platformApply<feBlendLighten>(sourcePixelA, sourcePixelB, destinationPix el, pixelArrayLength);
139 break;
140 case FEBLEND_MODE_UNKNOWN:
141 platformApply<feBlendUnknown>(sourcePixelA, sourcePixelB, destinationPix el, pixelArrayLength);
142 break;
143 }
144 }
145
146 void FEBlend::applySoftware() 84 void FEBlend::applySoftware()
147 { 85 {
148 FilterEffect* in = inputEffect(0); 86 FilterEffect* in = inputEffect(0);
149 FilterEffect* in2 = inputEffect(1); 87 FilterEffect* in2 = inputEffect(1);
150 88
151 ASSERT(m_mode > FEBLEND_MODE_UNKNOWN); 89 ASSERT(m_mode > FEBLEND_MODE_UNKNOWN && m_mode <= FEBLEND_MODE_LIGHTEN);
152 ASSERT(m_mode <= FEBLEND_MODE_LIGHTEN);
153 90
91 #if HAVE(ARM_NEON_INTRINSICS)
154 Uint8ClampedArray* dstPixelArray = createPremultipliedImageResult(); 92 Uint8ClampedArray* dstPixelArray = createPremultipliedImageResult();
155 if (!dstPixelArray) 93 if (!dstPixelArray)
156 return; 94 return;
157 95
158 IntRect effectADrawingRect = requestedRegionOfInputImageData(in->absolutePai ntRect()); 96 IntRect effectADrawingRect = requestedRegionOfInputImageData(in->absolutePai ntRect());
159 RefPtr<Uint8ClampedArray> srcPixelArrayA = in->asPremultipliedImage(effectAD rawingRect); 97 RefPtr<Uint8ClampedArray> srcPixelArrayA = in->asPremultipliedImage(effectAD rawingRect);
160 98
161 IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->absolutePa intRect()); 99 IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->absolutePa intRect());
162 RefPtr<Uint8ClampedArray> srcPixelArrayB = in2->asPremultipliedImage(effectB DrawingRect); 100 RefPtr<Uint8ClampedArray> srcPixelArrayB = in2->asPremultipliedImage(effectB DrawingRect);
163 101
164 unsigned pixelArrayLength = srcPixelArrayA->length(); 102 unsigned pixelArrayLength = srcPixelArrayA->length();
165 ASSERT(pixelArrayLength == srcPixelArrayB->length()); 103 ASSERT(pixelArrayLength == srcPixelArrayB->length());
166 104
167 #if HAVE(ARM_NEON_INTRINSICS)
168 if (pixelArrayLength >= 8) { 105 if (pixelArrayLength >= 8) {
169 platformApplyNEON(srcPixelArrayA->data(), srcPixelArrayB->data(), dstPix elArray->data(), pixelArrayLength); 106 platformApplyNEON(srcPixelArrayA->data(), srcPixelArrayB->data(), dstPix elArray->data(), pixelArrayLength);
170 } 107 } else {
171 else { // If there is just one pixel we expand it to two. 108 // If there is just one pixel we expand it to two.
172 ASSERT(pixelArrayLength > 0); 109 ASSERT(pixelArrayLength > 0);
173 uint32_t sourceA[2] = {0, 0}; 110 uint32_t sourceA[2] = {0, 0};
174 uint32_t sourceBAndDest[2] = {0, 0}; 111 uint32_t sourceBAndDest[2] = {0, 0};
175 112
176 sourceA[0] = reinterpret_cast<uint32_t*>(srcPixelArrayA->data())[0]; 113 sourceA[0] = reinterpret_cast<uint32_t*>(srcPixelArrayA->data())[0];
177 sourceBAndDest[0] = reinterpret_cast<uint32_t*>(srcPixelArrayB->data())[ 0]; 114 sourceBAndDest[0] = reinterpret_cast<uint32_t*>(srcPixelArrayB->data())[ 0];
178 platformApplyNEON(reinterpret_cast<uint8_t*>(sourceA), reinterpret_cast< uint8_t*>(sourceBAndDest), reinterpret_cast<uint8_t*>(sourceBAndDest), 8); 115 platformApplyNEON(reinterpret_cast<uint8_t*>(sourceA), reinterpret_cast< uint8_t*>(sourceBAndDest), reinterpret_cast<uint8_t*>(sourceBAndDest), 8);
179 reinterpret_cast<uint32_t*>(dstPixelArray->data())[0] = sourceBAndDest[0 ]; 116 reinterpret_cast<uint32_t*>(dstPixelArray->data())[0] = sourceBAndDest[0 ];
180 } 117 }
181 #else 118 #else
182 platformApplyGeneric(srcPixelArrayA->data(), srcPixelArrayB->data(), dstPixe lArray->data(), pixelArrayLength); 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 WebBlendMode blendMode = toWebBlendMode(m_mode);
130 filterContext->drawImageBuffer(imageBuffer2, drawingRegionOfInputImage(in2-> absolutePaintRect()));
131 filterContext->drawImageBuffer(imageBuffer, drawingRegionOfInputImage(in->ab solutePaintRect()), 0, CompositeSourceOver, blendMode);
f(malita) 2014/07/24 16:23:49 Did you run some perf measurements by any chance?
fs 2014/07/25 10:52:00 I wrote a simple TC that filled the viewport w/ re
183 #endif 132 #endif
184 } 133 }
185 134
186 static SkXfermode::Mode toSkiaMode(BlendModeType mode)
187 {
188 switch (mode) {
189 case FEBLEND_MODE_NORMAL:
190 return SkXfermode::kSrcOver_Mode;
191 case FEBLEND_MODE_MULTIPLY:
192 return SkXfermode::kMultiply_Mode;
193 case FEBLEND_MODE_SCREEN:
194 return SkXfermode::kScreen_Mode;
195 case FEBLEND_MODE_DARKEN:
196 return SkXfermode::kDarken_Mode;
197 case FEBLEND_MODE_LIGHTEN:
198 return SkXfermode::kLighten_Mode;
199 default:
200 return SkXfermode::kSrcOver_Mode;
201 }
202 }
203
204 PassRefPtr<SkImageFilter> FEBlend::createImageFilter(SkiaImageFilterBuilder* bui lder) 135 PassRefPtr<SkImageFilter> FEBlend::createImageFilter(SkiaImageFilterBuilder* bui lder)
205 { 136 {
206 RefPtr<SkImageFilter> foreground(builder->build(inputEffect(0), operatingCol orSpace())); 137 RefPtr<SkImageFilter> foreground(builder->build(inputEffect(0), operatingCol orSpace()));
207 RefPtr<SkImageFilter> background(builder->build(inputEffect(1), operatingCol orSpace())); 138 RefPtr<SkImageFilter> background(builder->build(inputEffect(1), operatingCol orSpace()));
208 SkAutoTUnref<SkXfermode> mode(SkXfermode::Create(toSkiaMode(m_mode))); 139 RefPtr<SkXfermode> mode(WebCoreCompositeToSkiaComposite(CompositeSourceOver, toWebBlendMode(m_mode)));
209 SkImageFilter::CropRect cropRect = getCropRect(builder->cropOffset()); 140 SkImageFilter::CropRect cropRect = getCropRect(builder->cropOffset());
210 return adoptRef(SkXfermodeImageFilter::Create(mode, background.get(), foregr ound.get(), &cropRect)); 141 return adoptRef(SkXfermodeImageFilter::Create(mode.get(), background.get(), foreground.get(), &cropRect));
211 } 142 }
212 143
213 static TextStream& operator<<(TextStream& ts, const BlendModeType& type) 144 static TextStream& operator<<(TextStream& ts, const BlendModeType& type)
214 { 145 {
215 switch (type) { 146 switch (type) {
216 case FEBLEND_MODE_UNKNOWN: 147 case FEBLEND_MODE_UNKNOWN:
217 ts << "UNKNOWN"; 148 ts << "UNKNOWN";
218 break; 149 break;
219 case FEBLEND_MODE_NORMAL: 150 case FEBLEND_MODE_NORMAL:
220 ts << "NORMAL"; 151 ts << "NORMAL";
(...skipping 19 matching lines...) Expand all
240 writeIndent(ts, indent); 171 writeIndent(ts, indent);
241 ts << "[feBlend"; 172 ts << "[feBlend";
242 FilterEffect::externalRepresentation(ts); 173 FilterEffect::externalRepresentation(ts);
243 ts << " mode=\"" << m_mode << "\"]\n"; 174 ts << " mode=\"" << m_mode << "\"]\n";
244 inputEffect(0)->externalRepresentation(ts, indent + 1); 175 inputEffect(0)->externalRepresentation(ts, indent + 1);
245 inputEffect(1)->externalRepresentation(ts, indent + 1); 176 inputEffect(1)->externalRepresentation(ts, indent + 1);
246 return ts; 177 return ts;
247 } 178 }
248 179
249 } // namespace blink 180 } // namespace blink
OLDNEW
« Source/platform/graphics/ImageBuffer.cpp ('K') | « Source/platform/graphics/ImageBuffer.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698