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

Side by Side Diff: cc/render_surface_filters.cc

Issue 12614011: cc: Chromify RenderSurfaceFilters. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: .f Created 7 years, 9 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
« no previous file with comments | « cc/render_surface_filters.h ('k') | cc/render_surface_filters_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 The Chromium Authors. All rights reserved. 1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "cc/render_surface_filters.h" 5 #include "cc/render_surface_filters.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "skia/ext/refptr.h" 8 #include "skia/ext/refptr.h"
9 #include "third_party/WebKit/Source/Platform/chromium/public/WebFilterOperation. h" 9 #include "third_party/WebKit/Source/Platform/chromium/public/WebFilterOperation. h"
10 #include "third_party/WebKit/Source/Platform/chromium/public/WebFilterOperations .h" 10 #include "third_party/WebKit/Source/Platform/chromium/public/WebFilterOperations .h"
11 #include "third_party/skia/include/core/SkCanvas.h" 11 #include "third_party/skia/include/core/SkCanvas.h"
12 #include "third_party/skia/include/effects/SkBlurImageFilter.h" 12 #include "third_party/skia/include/effects/SkBlurImageFilter.h"
13 #include "third_party/skia/include/effects/SkColorMatrixFilter.h" 13 #include "third_party/skia/include/effects/SkColorMatrixFilter.h"
14 #include "third_party/skia/include/effects/SkMagnifierImageFilter.h" 14 #include "third_party/skia/include/effects/SkMagnifierImageFilter.h"
15 #include "third_party/skia/include/gpu/SkGpuDevice.h" 15 #include "third_party/skia/include/gpu/SkGpuDevice.h"
16 #include "third_party/skia/include/gpu/SkGrPixelRef.h" 16 #include "third_party/skia/include/gpu/SkGrPixelRef.h"
17 #include "ui/gfx/size_f.h" 17 #include "ui/gfx/size_f.h"
18 18
19 namespace cc { 19 namespace cc {
20 20
21 namespace { 21 namespace {
22 22
23 void getBrightnessMatrix(float amount, SkScalar matrix[20]) 23 void GetBrightnessMatrix(float amount, SkScalar matrix[20]) {
24 { 24 // Spec implementation
25 // Spec implementation 25 // (http://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#brightnessEquiv alent)
26 // (http://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#brightnessEqu ivalent) 26 // <feFunc[R|G|B] type="linear" slope="[amount]">
27 // <feFunc[R|G|B] type="linear" slope="[amount]"> 27 memset(matrix, 0, 20 * sizeof(SkScalar));
28 memset(matrix, 0, 20 * sizeof(SkScalar)); 28 matrix[0] = matrix[6] = matrix[12] = amount;
29 matrix[0] = matrix[6] = matrix[12] = amount; 29 matrix[18] = 1.f;
30 matrix[18] = 1;
31 } 30 }
32 31
33 void getSaturatingBrightnessMatrix(float amount, SkScalar matrix[20]) 32 void GetSaturatingBrightnessMatrix(float amount, SkScalar matrix[20]) {
34 { 33 // Legacy implementation used by internal clients.
35 // Legacy implementation used by internal clients. 34 // <feFunc[R|G|B] type="linear" intercept="[amount]"/>
36 // <feFunc[R|G|B] type="linear" intercept="[amount]"/> 35 memset(matrix, 0, 20 * sizeof(SkScalar));
37 memset(matrix, 0, 20 * sizeof(SkScalar)); 36 matrix[0] = matrix[6] = matrix[12] = matrix[18] = 1.f;
38 matrix[0] = matrix[6] = matrix[12] = matrix[18] = 1; 37 matrix[4] = matrix[9] = matrix[14] = amount * 255.f;
39 matrix[4] = matrix[9] = matrix[14] = amount * 255;
40 } 38 }
41 39
42 void getContrastMatrix(float amount, SkScalar matrix[20]) 40 void GetContrastMatrix(float amount, SkScalar matrix[20]) {
43 { 41 memset(matrix, 0, 20 * sizeof(SkScalar));
44 memset(matrix, 0, 20 * sizeof(SkScalar)); 42 matrix[0] = matrix[6] = matrix[12] = amount;
45 matrix[0] = matrix[6] = matrix[12] = amount; 43 matrix[4] = matrix[9] = matrix[14] = (-0.5f * amount + 0.5f) * 255.f;
46 matrix[4] = matrix[9] = matrix[14] = (-0.5f * amount + 0.5f) * 255; 44 matrix[18] = 1.f;
47 matrix[18] = 1;
48 } 45 }
49 46
50 void getSaturateMatrix(float amount, SkScalar matrix[20]) 47 void GetSaturateMatrix(float amount, SkScalar matrix[20]) {
51 { 48 // Note, these values are computed to ensure matrixNeedsClamping is false
52 // Note, these values are computed to ensure matrixNeedsClamping is false 49 // for amount in [0..1]
53 // for amount in [0..1] 50 matrix[0] = 0.213f + 0.787f * amount;
54 matrix[0] = 0.213f + 0.787f * amount; 51 matrix[1] = 0.715f - 0.715f * amount;
55 matrix[1] = 0.715f - 0.715f * amount; 52 matrix[2] = 1.f - (matrix[0] + matrix[1]);
56 matrix[2] = 1.f - (matrix[0] + matrix[1]); 53 matrix[3] = matrix[4] = 0.f;
57 matrix[3] = matrix[4] = 0; 54 matrix[5] = 0.213f - 0.213f * amount;
58 matrix[5] = 0.213f - 0.213f * amount; 55 matrix[6] = 0.715f + 0.285f * amount;
59 matrix[6] = 0.715f + 0.285f * amount; 56 matrix[7] = 1.f - (matrix[5] + matrix[6]);
60 matrix[7] = 1.f - (matrix[5] + matrix[6]); 57 matrix[8] = matrix[9] = 0.f;
61 matrix[8] = matrix[9] = 0; 58 matrix[10] = 0.213f - 0.213f * amount;
62 matrix[10] = 0.213f - 0.213f * amount; 59 matrix[11] = 0.715f - 0.715f * amount;
63 matrix[11] = 0.715f - 0.715f * amount; 60 matrix[12] = 1.f - (matrix[10] + matrix[11]);
64 matrix[12] = 1.f - (matrix[10] + matrix[11]); 61 matrix[13] = matrix[14] = 0.f;
65 matrix[13] = matrix[14] = 0; 62 matrix[15] = matrix[16] = matrix[17] = matrix[19] = 0.f;
66 matrix[15] = matrix[16] = matrix[17] = matrix[19] = 0; 63 matrix[18] = 1.f;
67 matrix[18] = 1;
68 } 64 }
69 65
70 void getHueRotateMatrix(float hue, SkScalar matrix[20]) 66 void GetHueRotateMatrix(float hue, SkScalar matrix[20]) {
71 { 67 const float kPi = 3.1415926535897932384626433832795f;
72 const float kPi = 3.1415926535897932384626433832795f;
73 68
74 float cosHue = cosf(hue * kPi / 180); 69 float cos_hue = cosf(hue * kPi / 180.f);
75 float sinHue = sinf(hue * kPi / 180); 70 float sin_hue = sinf(hue * kPi / 180.f);
76 matrix[0] = 0.213f + cosHue * 0.787f - sinHue * 0.213f; 71 matrix[0] = 0.213f + cos_hue * 0.787f - sin_hue * 0.213f;
77 matrix[1] = 0.715f - cosHue * 0.715f - sinHue * 0.715f; 72 matrix[1] = 0.715f - cos_hue * 0.715f - sin_hue * 0.715f;
78 matrix[2] = 0.072f - cosHue * 0.072f + sinHue * 0.928f; 73 matrix[2] = 0.072f - cos_hue * 0.072f + sin_hue * 0.928f;
79 matrix[3] = matrix[4] = 0; 74 matrix[3] = matrix[4] = 0.f;
80 matrix[5] = 0.213f - cosHue * 0.213f + sinHue * 0.143f; 75 matrix[5] = 0.213f - cos_hue * 0.213f + sin_hue * 0.143f;
81 matrix[6] = 0.715f + cosHue * 0.285f + sinHue * 0.140f; 76 matrix[6] = 0.715f + cos_hue * 0.285f + sin_hue * 0.140f;
82 matrix[7] = 0.072f - cosHue * 0.072f - sinHue * 0.283f; 77 matrix[7] = 0.072f - cos_hue * 0.072f - sin_hue * 0.283f;
83 matrix[8] = matrix[9] = 0; 78 matrix[8] = matrix[9] = 0.f;
84 matrix[10] = 0.213f - cosHue * 0.213f - sinHue * 0.787f; 79 matrix[10] = 0.213f - cos_hue * 0.213f - sin_hue * 0.787f;
85 matrix[11] = 0.715f - cosHue * 0.715f + sinHue * 0.715f; 80 matrix[11] = 0.715f - cos_hue * 0.715f + sin_hue * 0.715f;
86 matrix[12] = 0.072f + cosHue * 0.928f + sinHue * 0.072f; 81 matrix[12] = 0.072f + cos_hue * 0.928f + sin_hue * 0.072f;
87 matrix[13] = matrix[14] = 0; 82 matrix[13] = matrix[14] = 0.f;
88 matrix[15] = matrix[16] = matrix[17] = 0; 83 matrix[15] = matrix[16] = matrix[17] = 0.f;
89 matrix[18] = 1; 84 matrix[18] = 1.f;
90 matrix[19] = 0; 85 matrix[19] = 0.f;
91 } 86 }
92 87
93 void getInvertMatrix(float amount, SkScalar matrix[20]) 88 void GetInvertMatrix(float amount, SkScalar matrix[20]) {
94 { 89 memset(matrix, 0, 20 * sizeof(SkScalar));
95 memset(matrix, 0, 20 * sizeof(SkScalar)); 90 matrix[0] = matrix[6] = matrix[12] = 1.f - 2.f * amount;
96 matrix[0] = matrix[6] = matrix[12] = 1 - 2 * amount; 91 matrix[4] = matrix[9] = matrix[14] = amount * 255.f;
97 matrix[4] = matrix[9] = matrix[14] = amount * 255; 92 matrix[18] = 1.f;
98 matrix[18] = 1;
99 } 93 }
100 94
101 void getOpacityMatrix(float amount, SkScalar matrix[20]) 95 void GetOpacityMatrix(float amount, SkScalar matrix[20]) {
102 { 96 memset(matrix, 0, 20 * sizeof(SkScalar));
103 memset(matrix, 0, 20 * sizeof(SkScalar)); 97 matrix[0] = matrix[6] = matrix[12] = 1.f;
104 matrix[0] = matrix[6] = matrix[12] = 1; 98 matrix[18] = amount;
105 matrix[18] = amount;
106 } 99 }
107 100
108 void getGrayscaleMatrix(float amount, SkScalar matrix[20]) 101 void GetGrayscaleMatrix(float amount, SkScalar matrix[20]) {
109 { 102 // Note, these values are computed to ensure matrixNeedsClamping is false
110 // Note, these values are computed to ensure matrixNeedsClamping is false 103 // for amount in [0..1]
111 // for amount in [0..1] 104 matrix[0] = 0.2126f + 0.7874f * amount;
112 matrix[0] = 0.2126f + 0.7874f * amount; 105 matrix[1] = 0.7152f - 0.7152f * amount;
113 matrix[1] = 0.7152f - 0.7152f * amount; 106 matrix[2] = 1.f - (matrix[0] + matrix[1]);
114 matrix[2] = 1.f - (matrix[0] + matrix[1]); 107 matrix[3] = matrix[4] = 0.f;
115 matrix[3] = matrix[4] = 0;
116 108
117 matrix[5] = 0.2126f - 0.2126f * amount; 109 matrix[5] = 0.2126f - 0.2126f * amount;
118 matrix[6] = 0.7152f + 0.2848f * amount; 110 matrix[6] = 0.7152f + 0.2848f * amount;
119 matrix[7] = 1.f - (matrix[5] + matrix[6]); 111 matrix[7] = 1.f - (matrix[5] + matrix[6]);
120 matrix[8] = matrix[9] = 0; 112 matrix[8] = matrix[9] = 0.f;
121 113
122 matrix[10] = 0.2126f - 0.2126f * amount; 114 matrix[10] = 0.2126f - 0.2126f * amount;
123 matrix[11] = 0.7152f - 0.7152f * amount; 115 matrix[11] = 0.7152f - 0.7152f * amount;
124 matrix[12] = 1.f - (matrix[10] + matrix[11]); 116 matrix[12] = 1.f - (matrix[10] + matrix[11]);
125 matrix[13] = matrix[14] = 0; 117 matrix[13] = matrix[14] = 0.f;
126 118
127 matrix[15] = matrix[16] = matrix[17] = matrix[19] = 0; 119 matrix[15] = matrix[16] = matrix[17] = matrix[19] = 0.f;
128 matrix[18] = 1; 120 matrix[18] = 1.f;
129 } 121 }
130 122
131 void getSepiaMatrix(float amount, SkScalar matrix[20]) 123 void GetSepiaMatrix(float amount, SkScalar matrix[20]) {
132 { 124 matrix[0] = 0.393f + 0.607f * amount;
133 matrix[0] = 0.393f + 0.607f * amount; 125 matrix[1] = 0.769f - 0.769f * amount;
134 matrix[1] = 0.769f - 0.769f * amount; 126 matrix[2] = 0.189f - 0.189f * amount;
135 matrix[2] = 0.189f - 0.189f * amount; 127 matrix[3] = matrix[4] = 0.f;
136 matrix[3] = matrix[4] = 0;
137 128
138 matrix[5] = 0.349f - 0.349f * amount; 129 matrix[5] = 0.349f - 0.349f * amount;
139 matrix[6] = 0.686f + 0.314f * amount; 130 matrix[6] = 0.686f + 0.314f * amount;
140 matrix[7] = 0.168f - 0.168f * amount; 131 matrix[7] = 0.168f - 0.168f * amount;
141 matrix[8] = matrix[9] = 0; 132 matrix[8] = matrix[9] = 0.f;
142 133
143 matrix[10] = 0.272f - 0.272f * amount; 134 matrix[10] = 0.272f - 0.272f * amount;
144 matrix[11] = 0.534f - 0.534f * amount; 135 matrix[11] = 0.534f - 0.534f * amount;
145 matrix[12] = 0.131f + 0.869f * amount; 136 matrix[12] = 0.131f + 0.869f * amount;
146 matrix[13] = matrix[14] = 0; 137 matrix[13] = matrix[14] = 0.f;
147 138
148 matrix[15] = matrix[16] = matrix[17] = matrix[19] = 0; 139 matrix[15] = matrix[16] = matrix[17] = matrix[19] = 0.f;
149 matrix[18] = 1; 140 matrix[18] = 1.f;
150 } 141 }
151 142
152 // The 5x4 matrix is really a "compressed" version of a 5x5 matrix that'd have 143 // The 5x4 matrix is really a "compressed" version of a 5x5 matrix that'd have
153 // (0 0 0 0 1) as a last row, and that would be applied to a 5-vector extended 144 // (0 0 0 0 1) as a last row, and that would be applied to a 5-vector extended
154 // from the 4-vector color with a 1. 145 // from the 4-vector color with a 1.
155 void multColorMatrix(SkScalar a[20], SkScalar b[20], SkScalar out[20]) 146 void MultColorMatrix(SkScalar a[20], SkScalar b[20], SkScalar out[20]) {
156 { 147 for (int j = 0; j < 4; ++j) {
157 for (int j = 0; j < 4; ++j) { 148 for (int i = 0; i < 5; ++i) {
158 for (int i = 0; i < 5; ++i) { 149 out[i+j*5] = i == 4 ? a[4+j*5] : 0.f;
159 out[i+j*5] = i == 4 ? a[4+j*5] : 0; 150 for (int k = 0; k < 4; ++k)
160 for (int k = 0; k < 4; ++k) 151 out[i+j*5] += a[k+j*5] * b[i+k*5];
161 out[i+j*5] += a[k+j*5] * b[i+k*5];
162 }
163 } 152 }
153 }
164 } 154 }
165 155
166 // To detect if we need to apply clamping after applying a matrix, we check if 156 // To detect if we need to apply clamping after applying a matrix, we check if
167 // any output component might go outside of [0, 255] for any combination of 157 // any output component might go outside of [0, 255] for any combination of
168 // input components in [0..255]. 158 // input components in [0..255].
169 // Each output component is an affine transformation of the input component, so 159 // Each output component is an affine transformation of the input component, so
170 // the minimum and maximum values are for any combination of minimum or maximum 160 // the minimum and maximum values are for any combination of minimum or maximum
171 // values of input components (i.e. 0 or 255). 161 // values of input components (i.e. 0 or 255).
172 // E.g. if R' = x*R + y*G + z*B + w*A + t 162 // E.g. if R' = x*R + y*G + z*B + w*A + t
173 // Then the maximum value will be for R=255 if x>0 or R=0 if x<0, and the 163 // Then the maximum value will be for R=255 if x>0 or R=0 if x<0, and the
174 // minimum value will be for R=0 if x>0 or R=255 if x<0. 164 // minimum value will be for R=0 if x>0 or R=255 if x<0.
175 // Same goes for all components. 165 // Same goes for all components.
176 bool componentNeedsClamping(SkScalar row[5]) 166 bool ComponentNeedsClamping(SkScalar row[5]) {
177 { 167 SkScalar max_value = row[4] / 255.f;
178 SkScalar maxValue = row[4] / 255; 168 SkScalar min_value = row[4] / 255.f;
179 SkScalar minValue = row[4] / 255; 169 for (int i = 0; i < 4; ++i) {
180 for (int i = 0; i < 4; ++i) { 170 if (row[i] > 0)
181 if (row[i] > 0) 171 max_value += row[i];
182 maxValue += row[i]; 172 else
183 else 173 min_value += row[i];
184 minValue += row[i]; 174 }
185 } 175 return (max_value > 1.f) || (min_value < 0.f);
186 return (maxValue > 1) || (minValue < 0); 176 }
187 } 177
188 178 bool MatrixNeedsClamping(SkScalar matrix[20]) {
189 bool matrixNeedsClamping(SkScalar matrix[20]) 179 return ComponentNeedsClamping(matrix)
190 { 180 || ComponentNeedsClamping(matrix+5)
191 return componentNeedsClamping(matrix) 181 || ComponentNeedsClamping(matrix+10)
192 || componentNeedsClamping(matrix+5) 182 || ComponentNeedsClamping(matrix+15);
193 || componentNeedsClamping(matrix+10) 183 }
194 || componentNeedsClamping(matrix+15); 184
195 } 185 bool GetColorMatrix(const WebKit::WebFilterOperation& op, SkScalar matrix[20]) {
196 186 switch (op.type()) {
197 bool getColorMatrix(const WebKit::WebFilterOperation& op, SkScalar matrix[20]) 187 case WebKit::WebFilterOperation::FilterTypeBrightness: {
198 { 188 GetBrightnessMatrix(op.amount(), matrix);
189 return true;
190 }
191 case WebKit::WebFilterOperation::FilterTypeSaturatingBrightness: {
192 GetSaturatingBrightnessMatrix(op.amount(), matrix);
193 return true;
194 }
195 case WebKit::WebFilterOperation::FilterTypeContrast: {
196 GetContrastMatrix(op.amount(), matrix);
197 return true;
198 }
199 case WebKit::WebFilterOperation::FilterTypeGrayscale: {
200 GetGrayscaleMatrix(1.f - op.amount(), matrix);
201 return true;
202 }
203 case WebKit::WebFilterOperation::FilterTypeSepia: {
204 GetSepiaMatrix(1.f - op.amount(), matrix);
205 return true;
206 }
207 case WebKit::WebFilterOperation::FilterTypeSaturate: {
208 GetSaturateMatrix(op.amount(), matrix);
209 return true;
210 }
211 case WebKit::WebFilterOperation::FilterTypeHueRotate: {
212 GetHueRotateMatrix(op.amount(), matrix);
213 return true;
214 }
215 case WebKit::WebFilterOperation::FilterTypeInvert: {
216 GetInvertMatrix(op.amount(), matrix);
217 return true;
218 }
219 case WebKit::WebFilterOperation::FilterTypeOpacity: {
220 GetOpacityMatrix(op.amount(), matrix);
221 return true;
222 }
223 case WebKit::WebFilterOperation::FilterTypeColorMatrix: {
224 memcpy(matrix, op.matrix(), sizeof(SkScalar[20]));
225 return true;
226 }
227 default:
228 return false;
229 }
230 }
231
232 class FilterBufferState {
233 public:
234 FilterBufferState(GrContext* gr_context,
235 gfx::SizeF size,
236 unsigned texture_id)
237 : gr_context_(gr_context),
238 current_texture_(0) {
239 // Wrap the source texture in a Ganesh platform texture.
240 GrBackendTextureDesc backend_texture_description;
241 backend_texture_description.fWidth = size.width();
242 backend_texture_description.fHeight = size.height();
243 backend_texture_description.fConfig = kSkia8888_GrPixelConfig;
244 backend_texture_description.fTextureHandle = texture_id;
245 skia::RefPtr<GrTexture> texture = skia::AdoptRef(
246 gr_context->wrapBackendTexture(backend_texture_description));
247 // Place the platform texture inside an SkBitmap.
248 source_.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height());
249 skia::RefPtr<SkGrPixelRef> pixel_ref =
250 skia::AdoptRef(new SkGrPixelRef(texture.get()));
251 source_.setPixelRef(pixel_ref.get());
252 }
253
254 ~FilterBufferState() {}
255
256 bool Init(int filter_count) {
257 int scratch_count = std::min(2, filter_count);
258 GrTextureDesc desc;
259 desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
260 desc.fSampleCnt = 0;
261 desc.fWidth = source_.width();
262 desc.fHeight = source_.height();
263 desc.fConfig = kSkia8888_GrPixelConfig;
264 for (int i = 0; i < scratch_count; ++i) {
265 GrAutoScratchTexture scratch_texture(
266 gr_context_, desc, GrContext::kExact_ScratchTexMatch);
267 scratch_textures_[i] = skia::AdoptRef(scratch_texture.detach());
268 if (!scratch_textures_[i])
269 return false;
270 }
271 return true;
272 }
273
274 SkCanvas* Canvas() {
275 if (!canvas_.get())
276 CreateCanvas();
277 return canvas_.get();
278 }
279
280 const SkBitmap& Source() { return source_; }
281
282 void Swap() {
283 canvas_->flush();
284 canvas_.clear();
285 device_.clear();
286
287 skia::RefPtr<SkGrPixelRef> pixel_ref = skia::AdoptRef(
288 new SkGrPixelRef(scratch_textures_[current_texture_].get()));
289 source_.setPixelRef(pixel_ref.get());
290 current_texture_ = 1 - current_texture_;
291 }
292
293 private:
294 void CreateCanvas() {
295 DCHECK(scratch_textures_[current_texture_].get());
296 device_ = skia::AdoptRef(new SkGpuDevice(
297 gr_context_, scratch_textures_[current_texture_].get()));
298 canvas_ = skia::AdoptRef(new SkCanvas(device_.get()));
299 canvas_->clear(0x0);
300 }
301
302 GrContext* gr_context_;
303 SkBitmap source_;
304 skia::RefPtr<GrTexture> scratch_textures_[2];
305 int current_texture_;
306 skia::RefPtr<SkGpuDevice> device_;
307 skia::RefPtr<SkCanvas> canvas_;
308 };
309
310 } // namespace
311
312 WebKit::WebFilterOperations RenderSurfaceFilters::Optimize(
313 const WebKit::WebFilterOperations& filters) {
314 WebKit::WebFilterOperations new_list;
315
316 SkScalar accumulated_color_matrix[20];
317 bool have_accumulated_color_matrix = false;
318 for (unsigned i = 0; i < filters.size(); ++i) {
319 const WebKit::WebFilterOperation& op = filters.at(i);
320
321 // If the filter is a color matrix, we may be able to combine it with
322 // following filter(s) that also are color matrices.
323 SkScalar matrix[20];
324 if (GetColorMatrix(op, matrix)) {
325 if (have_accumulated_color_matrix) {
326 SkScalar newMatrix[20];
327 MultColorMatrix(matrix, accumulated_color_matrix, newMatrix);
328 memcpy(accumulated_color_matrix,
329 newMatrix,
330 sizeof(accumulated_color_matrix));
331 } else {
332 memcpy(accumulated_color_matrix,
333 matrix,
334 sizeof(accumulated_color_matrix));
335 have_accumulated_color_matrix = true;
336 }
337
338 // We can only combine matrices if clamping of color components
339 // would have no effect.
340 if (!MatrixNeedsClamping(accumulated_color_matrix))
341 continue;
342 }
343
344 if (have_accumulated_color_matrix) {
345 new_list.append(WebKit::WebFilterOperation::createColorMatrixFilter(
346 accumulated_color_matrix));
347 }
348 have_accumulated_color_matrix = false;
349
199 switch (op.type()) { 350 switch (op.type()) {
200 case WebKit::WebFilterOperation::FilterTypeBrightness: { 351 case WebKit::WebFilterOperation::FilterTypeBlur:
201 getBrightnessMatrix(op.amount(), matrix); 352 case WebKit::WebFilterOperation::FilterTypeDropShadow:
202 return true; 353 case WebKit::WebFilterOperation::FilterTypeZoom:
203 } 354 new_list.append(op);
204 case WebKit::WebFilterOperation::FilterTypeSaturatingBrightness: { 355 break;
205 getSaturatingBrightnessMatrix(op.amount(), matrix); 356 case WebKit::WebFilterOperation::FilterTypeBrightness:
206 return true; 357 case WebKit::WebFilterOperation::FilterTypeSaturatingBrightness:
207 } 358 case WebKit::WebFilterOperation::FilterTypeContrast:
208 case WebKit::WebFilterOperation::FilterTypeContrast: { 359 case WebKit::WebFilterOperation::FilterTypeGrayscale:
209 getContrastMatrix(op.amount(), matrix); 360 case WebKit::WebFilterOperation::FilterTypeSepia:
210 return true; 361 case WebKit::WebFilterOperation::FilterTypeSaturate:
211 } 362 case WebKit::WebFilterOperation::FilterTypeHueRotate:
212 case WebKit::WebFilterOperation::FilterTypeGrayscale: { 363 case WebKit::WebFilterOperation::FilterTypeInvert:
213 getGrayscaleMatrix(1 - op.amount(), matrix); 364 case WebKit::WebFilterOperation::FilterTypeOpacity:
214 return true; 365 case WebKit::WebFilterOperation::FilterTypeColorMatrix:
215 } 366 break;
216 case WebKit::WebFilterOperation::FilterTypeSepia: { 367 }
217 getSepiaMatrix(1 - op.amount(), matrix); 368 }
218 return true; 369 if (have_accumulated_color_matrix) {
219 } 370 new_list.append(WebKit::WebFilterOperation::createColorMatrixFilter(
220 case WebKit::WebFilterOperation::FilterTypeSaturate: { 371 accumulated_color_matrix));
221 getSaturateMatrix(op.amount(), matrix); 372 }
222 return true; 373 return new_list;
223 } 374 }
224 case WebKit::WebFilterOperation::FilterTypeHueRotate: { 375
225 getHueRotateMatrix(op.amount(), matrix); 376 SkBitmap RenderSurfaceFilters::Apply(const WebKit::WebFilterOperations& filters,
226 return true; 377 unsigned texture_id,
227 } 378 gfx::SizeF size,
228 case WebKit::WebFilterOperation::FilterTypeInvert: { 379 GrContext* gr_context) {
229 getInvertMatrix(op.amount(), matrix); 380 DCHECK(gr_context);
230 return true; 381
231 } 382 WebKit::WebFilterOperations optimized_filters = Optimize(filters);
232 case WebKit::WebFilterOperation::FilterTypeOpacity: { 383 FilterBufferState state(gr_context, size, texture_id);
233 getOpacityMatrix(op.amount(), matrix); 384 if (!state.Init(optimized_filters.size()))
234 return true; 385 return SkBitmap();
235 } 386
236 case WebKit::WebFilterOperation::FilterTypeColorMatrix: { 387 for (unsigned i = 0; i < optimized_filters.size(); ++i) {
237 memcpy(matrix, op.matrix(), sizeof(SkScalar[20])); 388 const WebKit::WebFilterOperation& op = optimized_filters.at(i);
238 return true; 389 SkCanvas* canvas = state.Canvas();
239 } 390 switch (op.type()) {
240 default: 391 case WebKit::WebFilterOperation::FilterTypeColorMatrix: {
241 return false; 392 SkPaint paint;
242 } 393 skia::RefPtr<SkColorMatrixFilter> filter =
243 } 394 skia::AdoptRef(new SkColorMatrixFilter(op.matrix()));
244 395 paint.setColorFilter(filter.get());
245 class FilterBufferState { 396 canvas->drawBitmap(state.Source(), 0, 0, &paint);
246 public: 397 break;
247 FilterBufferState(GrContext* grContext, const gfx::SizeF& size, unsigned tex tureId) 398 }
248 : m_grContext(grContext) 399 case WebKit::WebFilterOperation::FilterTypeBlur: {
249 , m_currentTexture(0) 400 float std_deviation = op.amount();
250 { 401 skia::RefPtr<SkImageFilter> filter =
251 // Wrap the source texture in a Ganesh platform texture. 402 skia::AdoptRef(new SkBlurImageFilter(std_deviation, std_deviation));
252 GrBackendTextureDesc backendTextureDescription; 403 SkPaint paint;
253 backendTextureDescription.fWidth = size.width(); 404 paint.setImageFilter(filter.get());
254 backendTextureDescription.fHeight = size.height(); 405 canvas->drawSprite(state.Source(), 0, 0, &paint);
255 backendTextureDescription.fConfig = kSkia8888_GrPixelConfig; 406 break;
256 backendTextureDescription.fTextureHandle = textureId; 407 }
257 skia::RefPtr<GrTexture> texture = skia::AdoptRef(grContext->wrapBackendT exture(backendTextureDescription)); 408 case WebKit::WebFilterOperation::FilterTypeDropShadow: {
258 // Place the platform texture inside an SkBitmap. 409 skia::RefPtr<SkImageFilter> blur_filter =
259 m_source.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.heigh t()); 410 skia::AdoptRef(new SkBlurImageFilter(op.amount(), op.amount()));
260 skia::RefPtr<SkGrPixelRef> pixelRef = skia::AdoptRef(new SkGrPixelRef(te xture.get())); 411 skia::RefPtr<SkColorFilter> color_filter =
261 m_source.setPixelRef(pixelRef.get()); 412 skia::AdoptRef(SkColorFilter::CreateModeFilter(
262 } 413 op.dropShadowColor(), SkXfermode::kSrcIn_Mode));
263 414 SkPaint paint;
264 ~FilterBufferState() { } 415 paint.setImageFilter(blur_filter.get());
265 416 paint.setColorFilter(color_filter.get());
266 bool init(int filterCount) 417 paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
267 { 418 canvas->saveLayer(NULL, &paint);
268 int scratchCount = std::min(2, filterCount); 419 canvas->drawBitmap(state.Source(),
269 GrTextureDesc desc; 420 op.dropShadowOffset().x,
270 desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagB it; 421 -op.dropShadowOffset().y);
271 desc.fSampleCnt = 0; 422 canvas->restore();
272 desc.fWidth = m_source.width(); 423 canvas->drawBitmap(state.Source(), 0, 0);
273 desc.fHeight = m_source.height(); 424 break;
274 desc.fConfig = kSkia8888_GrPixelConfig; 425 }
275 for (int i = 0; i < scratchCount; ++i) { 426 case WebKit::WebFilterOperation::FilterTypeZoom: {
276 GrAutoScratchTexture scratchTexture(m_grContext, desc, GrContext::kE xact_ScratchTexMatch); 427 SkPaint paint;
277 m_scratchTextures[i] = skia::AdoptRef(scratchTexture.detach()); 428 skia::RefPtr<SkImageFilter> zoom_filter = skia::AdoptRef(
278 if (!m_scratchTextures[i]) 429 new SkMagnifierImageFilter(
279 return false; 430 SkRect::MakeXYWH(op.zoomRect().x,
280 } 431 op.zoomRect().y,
281 return true; 432 op.zoomRect().width,
282 } 433 op.zoomRect().height),
283 434 op.amount()));
284 SkCanvas* canvas() 435 paint.setImageFilter(zoom_filter.get());
285 { 436 canvas->saveLayer(NULL, &paint);
286 if (!m_canvas.get()) 437 canvas->drawBitmap(state.Source(), 0, 0);
287 createCanvas(); 438 canvas->restore();
288 return m_canvas.get(); 439 break;
289 } 440 }
290 441 case WebKit::WebFilterOperation::FilterTypeBrightness:
291 const SkBitmap& source() { return m_source; } 442 case WebKit::WebFilterOperation::FilterTypeSaturatingBrightness:
292 443 case WebKit::WebFilterOperation::FilterTypeContrast:
293 void swap() 444 case WebKit::WebFilterOperation::FilterTypeGrayscale:
294 { 445 case WebKit::WebFilterOperation::FilterTypeSepia:
295 m_canvas->flush(); 446 case WebKit::WebFilterOperation::FilterTypeSaturate:
296 m_canvas.clear(); 447 case WebKit::WebFilterOperation::FilterTypeHueRotate:
297 m_device.clear(); 448 case WebKit::WebFilterOperation::FilterTypeInvert:
298 449 case WebKit::WebFilterOperation::FilterTypeOpacity:
299 skia::RefPtr<SkGrPixelRef> pixelRef = skia::AdoptRef(new SkGrPixelRef(m_ scratchTextures[m_currentTexture].get())); 450 NOTREACHED();
300 m_source.setPixelRef(pixelRef.get()); 451 break;
301 m_currentTexture = 1 - m_currentTexture; 452 }
302 } 453 state.Swap();
303 454 }
304 private: 455 return state.Source();
305 void createCanvas()
306 {
307 DCHECK(m_scratchTextures[m_currentTexture].get());
308 m_device = skia::AdoptRef(new SkGpuDevice(m_grContext, m_scratchTextures [m_currentTexture].get()));
309 m_canvas = skia::AdoptRef(new SkCanvas(m_device.get()));
310 m_canvas->clear(0x0);
311 }
312
313 GrContext* m_grContext;
314 SkBitmap m_source;
315 skia::RefPtr<GrTexture> m_scratchTextures[2];
316 int m_currentTexture;
317 skia::RefPtr<SkGpuDevice> m_device;
318 skia::RefPtr<SkCanvas> m_canvas;
319 };
320
321 } // namespace
322
323 WebKit::WebFilterOperations RenderSurfaceFilters::optimize(const WebKit::WebFilt erOperations& filters)
324 {
325 WebKit::WebFilterOperations newList;
326
327 SkScalar accumulatedColorMatrix[20];
328 bool haveAccumulatedColorMatrix = false;
329 for (unsigned i = 0; i < filters.size(); ++i) {
330 const WebKit::WebFilterOperation& op = filters.at(i);
331
332 // If the filter is a color matrix, we may be able to combine it with
333 // following filter(s) that also are color matrices.
334 SkScalar matrix[20];
335 if (getColorMatrix(op, matrix)) {
336 if (haveAccumulatedColorMatrix) {
337 SkScalar newMatrix[20];
338 multColorMatrix(matrix, accumulatedColorMatrix, newMatrix);
339 memcpy(accumulatedColorMatrix, newMatrix, sizeof(accumulatedColo rMatrix));
340 } else {
341 memcpy(accumulatedColorMatrix, matrix, sizeof(accumulatedColorMa trix));
342 haveAccumulatedColorMatrix = true;
343 }
344
345 // We can only combine matrices if clamping of color components
346 // would have no effect.
347 if (!matrixNeedsClamping(accumulatedColorMatrix))
348 continue;
349 }
350
351 if (haveAccumulatedColorMatrix)
352 newList.append(WebKit::WebFilterOperation::createColorMatrixFilter(a ccumulatedColorMatrix));
353 haveAccumulatedColorMatrix = false;
354
355 switch (op.type()) {
356 case WebKit::WebFilterOperation::FilterTypeBlur:
357 case WebKit::WebFilterOperation::FilterTypeDropShadow:
358 case WebKit::WebFilterOperation::FilterTypeZoom:
359 newList.append(op);
360 break;
361 case WebKit::WebFilterOperation::FilterTypeBrightness:
362 case WebKit::WebFilterOperation::FilterTypeSaturatingBrightness:
363 case WebKit::WebFilterOperation::FilterTypeContrast:
364 case WebKit::WebFilterOperation::FilterTypeGrayscale:
365 case WebKit::WebFilterOperation::FilterTypeSepia:
366 case WebKit::WebFilterOperation::FilterTypeSaturate:
367 case WebKit::WebFilterOperation::FilterTypeHueRotate:
368 case WebKit::WebFilterOperation::FilterTypeInvert:
369 case WebKit::WebFilterOperation::FilterTypeOpacity:
370 case WebKit::WebFilterOperation::FilterTypeColorMatrix:
371 break;
372 }
373 }
374 if (haveAccumulatedColorMatrix)
375 newList.append(WebKit::WebFilterOperation::createColorMatrixFilter(accum ulatedColorMatrix));
376 return newList;
377 }
378
379 SkBitmap RenderSurfaceFilters::apply(const WebKit::WebFilterOperations& filters, unsigned textureId, gfx::SizeF size, GrContext* grContext)
380 {
381 DCHECK(grContext);
382
383 WebKit::WebFilterOperations optimizedFilters = optimize(filters);
384 FilterBufferState state(grContext, size, textureId);
385 if (!state.init(optimizedFilters.size()))
386 return SkBitmap();
387
388 for (unsigned i = 0; i < optimizedFilters.size(); ++i) {
389 const WebKit::WebFilterOperation& op = optimizedFilters.at(i);
390 SkCanvas* canvas = state.canvas();
391 switch (op.type()) {
392 case WebKit::WebFilterOperation::FilterTypeColorMatrix: {
393 SkPaint paint;
394 skia::RefPtr<SkColorMatrixFilter> filter = skia::AdoptRef(new SkColo rMatrixFilter(op.matrix()));
395 paint.setColorFilter(filter.get());
396 canvas->drawBitmap(state.source(), 0, 0, &paint);
397 break;
398 }
399 case WebKit::WebFilterOperation::FilterTypeBlur: {
400 float stdDeviation = op.amount();
401 skia::RefPtr<SkImageFilter> filter = skia::AdoptRef(new SkBlurImageF ilter(stdDeviation, stdDeviation));
402 SkPaint paint;
403 paint.setImageFilter(filter.get());
404 canvas->drawSprite(state.source(), 0, 0, &paint);
405 break;
406 }
407 case WebKit::WebFilterOperation::FilterTypeDropShadow: {
408 skia::RefPtr<SkImageFilter> blurFilter = skia::AdoptRef(new SkBlurIm ageFilter(op.amount(), op.amount()));
409 skia::RefPtr<SkColorFilter> colorFilter = skia::AdoptRef(SkColorFilt er::CreateModeFilter(op.dropShadowColor(), SkXfermode::kSrcIn_Mode));
410 SkPaint paint;
411 paint.setImageFilter(blurFilter.get());
412 paint.setColorFilter(colorFilter.get());
413 paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
414 canvas->saveLayer(0, &paint);
415 canvas->drawBitmap(state.source(), op.dropShadowOffset().x, -op.drop ShadowOffset().y);
416 canvas->restore();
417 canvas->drawBitmap(state.source(), 0, 0);
418 break;
419 }
420 case WebKit::WebFilterOperation::FilterTypeZoom: {
421 SkPaint paint;
422 skia::RefPtr<SkImageFilter> zoomFilter = skia::AdoptRef(
423 new SkMagnifierImageFilter(
424 SkRect::MakeXYWH(op.zoomRect().x,
425 op.zoomRect().y,
426 op.zoomRect().width,
427 op.zoomRect().height),
428 op.amount()));
429 paint.setImageFilter(zoomFilter.get());
430 canvas->saveLayer(0, &paint);
431 canvas->drawBitmap(state.source(), 0, 0);
432 canvas->restore();
433 break;
434 }
435 case WebKit::WebFilterOperation::FilterTypeBrightness:
436 case WebKit::WebFilterOperation::FilterTypeSaturatingBrightness:
437 case WebKit::WebFilterOperation::FilterTypeContrast:
438 case WebKit::WebFilterOperation::FilterTypeGrayscale:
439 case WebKit::WebFilterOperation::FilterTypeSepia:
440 case WebKit::WebFilterOperation::FilterTypeSaturate:
441 case WebKit::WebFilterOperation::FilterTypeHueRotate:
442 case WebKit::WebFilterOperation::FilterTypeInvert:
443 case WebKit::WebFilterOperation::FilterTypeOpacity:
444 NOTREACHED();
445 break;
446 }
447 state.swap();
448 }
449 return state.source();
450 } 456 }
451 457
452 } // namespace cc 458 } // namespace cc
OLDNEW
« no previous file with comments | « cc/render_surface_filters.h ('k') | cc/render_surface_filters_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698