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

Side by Side Diff: cc/CCRenderSurfaceFilters.cpp

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

Powered by Google App Engine
This is Rietveld 408576698