OLD | NEW |
---|---|
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/output/render_surface_filters.h" | 5 #include "cc/output/render_surface_filters.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "cc/output/filter_operation.h" | 10 #include "cc/output/filter_operation.h" |
11 #include "cc/output/filter_operations.h" | 11 #include "cc/output/filter_operations.h" |
12 #include "skia/ext/refptr.h" | 12 #include "skia/ext/refptr.h" |
13 #include "third_party/skia/include/core/SkCanvas.h" | 13 #include "third_party/skia/include/core/SkCanvas.h" |
14 #include "third_party/skia/include/core/SkFlattenableBuffers.h" | |
15 #include "third_party/skia/include/core/SkImageFilter.h" | |
14 #include "third_party/skia/include/effects/SkBlurImageFilter.h" | 16 #include "third_party/skia/include/effects/SkBlurImageFilter.h" |
17 #include "third_party/skia/include/effects/SkColorFilterImageFilter.h" | |
15 #include "third_party/skia/include/effects/SkColorMatrixFilter.h" | 18 #include "third_party/skia/include/effects/SkColorMatrixFilter.h" |
16 #include "third_party/skia/include/effects/SkMagnifierImageFilter.h" | 19 #include "third_party/skia/include/effects/SkMagnifierImageFilter.h" |
20 #include "third_party/skia/include/effects/SkTestImageFilters.h" | |
ajuma
2013/07/31 18:40:37
This is for SkComposeImageFilter, used to connect
Stephen White
2013/07/31 19:18:51
Yes, I think it should be broken out into its own
ajuma
2013/09/09 17:35:36
Done.
| |
17 #include "third_party/skia/include/gpu/SkGpuDevice.h" | 21 #include "third_party/skia/include/gpu/SkGpuDevice.h" |
18 #include "third_party/skia/include/gpu/SkGrPixelRef.h" | 22 #include "third_party/skia/include/gpu/SkGrPixelRef.h" |
19 #include "ui/gfx/size_f.h" | 23 #include "ui/gfx/size_f.h" |
20 | 24 |
21 namespace cc { | 25 namespace cc { |
22 | 26 |
23 namespace { | 27 namespace { |
24 | 28 |
25 void GetBrightnessMatrix(float amount, SkScalar matrix[20]) { | 29 void GetBrightnessMatrix(float amount, SkScalar matrix[20]) { |
26 // Spec implementation | 30 // Spec implementation |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
224 } | 228 } |
225 case FilterOperation::COLOR_MATRIX: { | 229 case FilterOperation::COLOR_MATRIX: { |
226 memcpy(matrix, op.matrix(), sizeof(SkScalar[20])); | 230 memcpy(matrix, op.matrix(), sizeof(SkScalar[20])); |
227 return true; | 231 return true; |
228 } | 232 } |
229 default: | 233 default: |
230 return false; | 234 return false; |
231 } | 235 } |
232 } | 236 } |
233 | 237 |
238 skia::RefPtr<SkImageFilter> CreateMatrixImageFilter( | |
239 const SkScalar matrix[20], | |
240 skia::RefPtr<SkImageFilter> input) { | |
241 skia::RefPtr<SkColorFilter> color_filter = | |
242 skia::AdoptRef(new SkColorMatrixFilter(matrix)); | |
243 return skia::AdoptRef( | |
244 SkColorFilterImageFilter::Create(color_filter.get(), input.get())); | |
245 } | |
246 | |
234 class FilterBufferState { | 247 class FilterBufferState { |
235 public: | 248 public: |
236 FilterBufferState(GrContext* gr_context, | 249 FilterBufferState(GrContext* gr_context, |
237 gfx::SizeF size, | 250 gfx::SizeF size, |
238 unsigned texture_id) | 251 unsigned texture_id) |
239 : gr_context_(gr_context), | 252 : gr_context_(gr_context), |
240 current_texture_(0) { | 253 current_texture_(0) { |
241 // Wrap the source texture in a Ganesh platform texture. | 254 // Wrap the source texture in a Ganesh platform texture. |
242 GrBackendTextureDesc backend_texture_description; | 255 GrBackendTextureDesc backend_texture_description; |
243 backend_texture_description.fWidth = size.width(); | 256 backend_texture_description.fWidth = size.width(); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
302 } | 315 } |
303 | 316 |
304 GrContext* gr_context_; | 317 GrContext* gr_context_; |
305 SkBitmap source_; | 318 SkBitmap source_; |
306 skia::RefPtr<GrTexture> scratch_textures_[2]; | 319 skia::RefPtr<GrTexture> scratch_textures_[2]; |
307 int current_texture_; | 320 int current_texture_; |
308 skia::RefPtr<SkGpuDevice> device_; | 321 skia::RefPtr<SkGpuDevice> device_; |
309 skia::RefPtr<SkCanvas> canvas_; | 322 skia::RefPtr<SkCanvas> canvas_; |
310 }; | 323 }; |
311 | 324 |
325 class DropShadowImageFilter : public SkImageFilter { | |
ajuma
2013/07/31 18:40:37
This is copied from Blink. SkiaImageFilterBuilder
ajuma
2013/09/09 17:35:36
This is no longer needed, since DropShadowImageFil
| |
326 public: | |
327 DropShadowImageFilter(SkScalar dx, | |
328 SkScalar dy, | |
329 SkScalar sigma, | |
330 SkColor color, | |
331 SkImageFilter* input) | |
332 : SkImageFilter(input), | |
333 dx_(dx), | |
334 dy_(dy), | |
335 sigma_(sigma), | |
336 color_(color) { } | |
337 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(DropShadowImageFilter) | |
338 | |
339 protected: | |
340 explicit DropShadowImageFilter(SkFlattenableReadBuffer& buffer) | |
341 : SkImageFilter(buffer) { | |
342 dx_ = buffer.readScalar(); | |
343 dy_ = buffer.readScalar(); | |
344 sigma_ = buffer.readScalar(); | |
345 color_ = buffer.readColor(); | |
346 } | |
347 | |
348 virtual void flatten(SkFlattenableWriteBuffer& buffer) const OVERRIDE { | |
349 buffer.writeScalar(dx_); | |
350 buffer.writeScalar(dy_); | |
351 buffer.writeScalar(sigma_); | |
352 buffer.writeColor(color_); | |
353 } | |
354 | |
355 virtual bool onFilterImage(Proxy* proxy, | |
356 const SkBitmap& source, | |
357 const SkMatrix& matrix, | |
358 SkBitmap* result, | |
359 SkIPoint* loc) OVERRIDE { | |
360 SkBitmap src = source; | |
361 if (getInput(0) && | |
362 !getInput(0)->filterImage(proxy, source, matrix, &src, loc)) | |
363 return false; | |
364 | |
365 skia::RefPtr<SkDevice> device = skia::AdoptRef( | |
366 proxy->createDevice(src.width(), src.height())); | |
367 SkCanvas canvas(device.get()); | |
368 | |
369 skia::RefPtr<SkImageFilter> blurFilter = skia::AdoptRef( | |
370 new SkBlurImageFilter(sigma_, sigma_)); | |
371 skia::RefPtr<SkColorFilter> colorFilter = skia::AdoptRef( | |
372 SkColorFilter::CreateModeFilter(color_, SkXfermode::kSrcIn_Mode)); | |
373 SkPaint paint; | |
374 paint.setImageFilter(blurFilter.get()); | |
375 paint.setColorFilter(colorFilter.get()); | |
376 paint.setXfermodeMode(SkXfermode::kSrcOver_Mode); | |
377 canvas.saveLayer(0, &paint); | |
Stephen White
2013/07/31 19:18:51
FYI, we can probably get rid of the saveLayer()/re
| |
378 canvas.drawBitmap(src, dx_, dy_); | |
ajuma
2013/07/31 18:40:37
The version of DropShadowImageFilter currently in
Stephen White
2013/07/31 19:18:51
Yeah, I think that was when we had TopDown texture
| |
379 canvas.restore(); | |
380 canvas.drawBitmap(src, 0, 0); | |
381 *result = device.get()->accessBitmap(false); | |
382 return true; | |
383 } | |
384 | |
385 private: | |
386 SkScalar dx_, dy_, sigma_; | |
387 SkColor color_; | |
388 }; | |
389 | |
312 } // namespace | 390 } // namespace |
313 | 391 |
314 FilterOperations RenderSurfaceFilters::Optimize( | 392 FilterOperations RenderSurfaceFilters::Optimize( |
315 const FilterOperations& filters) { | 393 const FilterOperations& filters) { |
316 FilterOperations new_list; | 394 FilterOperations new_list; |
317 | 395 |
318 SkScalar accumulated_color_matrix[20]; | 396 SkScalar accumulated_color_matrix[20]; |
319 bool have_accumulated_color_matrix = false; | 397 bool have_accumulated_color_matrix = false; |
320 for (unsigned i = 0; i < filters.size(); ++i) { | 398 for (unsigned i = 0; i < filters.size(); ++i) { |
321 const FilterOperation& op = filters.at(i); | 399 const FilterOperation& op = filters.at(i); |
(...skipping 26 matching lines...) Expand all Loading... | |
348 accumulated_color_matrix)); | 426 accumulated_color_matrix)); |
349 } | 427 } |
350 have_accumulated_color_matrix = false; | 428 have_accumulated_color_matrix = false; |
351 | 429 |
352 switch (op.type()) { | 430 switch (op.type()) { |
353 case FilterOperation::BLUR: | 431 case FilterOperation::BLUR: |
354 case FilterOperation::DROP_SHADOW: | 432 case FilterOperation::DROP_SHADOW: |
355 case FilterOperation::ZOOM: | 433 case FilterOperation::ZOOM: |
356 new_list.Append(op); | 434 new_list.Append(op); |
357 break; | 435 break; |
436 case FilterOperation::REFERENCE: | |
437 // Not supported on this code path. | |
438 NOTREACHED(); | |
358 case FilterOperation::BRIGHTNESS: | 439 case FilterOperation::BRIGHTNESS: |
359 case FilterOperation::SATURATING_BRIGHTNESS: | 440 case FilterOperation::SATURATING_BRIGHTNESS: |
360 case FilterOperation::CONTRAST: | 441 case FilterOperation::CONTRAST: |
361 case FilterOperation::GRAYSCALE: | 442 case FilterOperation::GRAYSCALE: |
362 case FilterOperation::SEPIA: | 443 case FilterOperation::SEPIA: |
363 case FilterOperation::SATURATE: | 444 case FilterOperation::SATURATE: |
364 case FilterOperation::HUE_ROTATE: | 445 case FilterOperation::HUE_ROTATE: |
365 case FilterOperation::INVERT: | 446 case FilterOperation::INVERT: |
366 case FilterOperation::OPACITY: | 447 case FilterOperation::OPACITY: |
367 case FilterOperation::COLOR_MATRIX: | 448 case FilterOperation::COLOR_MATRIX: |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
435 (height - (height / op.amount())) / 2.f, | 516 (height - (height / op.amount())) / 2.f, |
436 width / op.amount(), | 517 width / op.amount(), |
437 height / op.amount()), | 518 height / op.amount()), |
438 op.zoom_inset())); | 519 op.zoom_inset())); |
439 paint.setImageFilter(zoom_filter.get()); | 520 paint.setImageFilter(zoom_filter.get()); |
440 canvas->saveLayer(NULL, &paint); | 521 canvas->saveLayer(NULL, &paint); |
441 canvas->drawBitmap(state.Source(), 0, 0); | 522 canvas->drawBitmap(state.Source(), 0, 0); |
442 canvas->restore(); | 523 canvas->restore(); |
443 break; | 524 break; |
444 } | 525 } |
526 case FilterOperation::REFERENCE: | |
445 case FilterOperation::BRIGHTNESS: | 527 case FilterOperation::BRIGHTNESS: |
446 case FilterOperation::SATURATING_BRIGHTNESS: | 528 case FilterOperation::SATURATING_BRIGHTNESS: |
447 case FilterOperation::CONTRAST: | 529 case FilterOperation::CONTRAST: |
448 case FilterOperation::GRAYSCALE: | 530 case FilterOperation::GRAYSCALE: |
449 case FilterOperation::SEPIA: | 531 case FilterOperation::SEPIA: |
450 case FilterOperation::SATURATE: | 532 case FilterOperation::SATURATE: |
451 case FilterOperation::HUE_ROTATE: | 533 case FilterOperation::HUE_ROTATE: |
452 case FilterOperation::INVERT: | 534 case FilterOperation::INVERT: |
453 case FilterOperation::OPACITY: | 535 case FilterOperation::OPACITY: |
454 NOTREACHED(); | 536 NOTREACHED(); |
455 break; | 537 break; |
456 } | 538 } |
457 state.Swap(); | 539 state.Swap(); |
458 } | 540 } |
459 return state.Source(); | 541 return state.Source(); |
460 } | 542 } |
461 | 543 |
544 skia::RefPtr<SkImageFilter> RenderSurfaceFilters::BuildImageFilter( | |
545 const FilterOperations& filters) { | |
546 skia::RefPtr<SkImageFilter> image_filter; | |
547 SkScalar matrix[20]; | |
548 for (size_t i = 0; i < filters.size(); ++i) { | |
549 const FilterOperation& op = filters.at(i); | |
550 switch (op.type()) { | |
551 case FilterOperation::GRAYSCALE: | |
552 GetGrayscaleMatrix(1 - op.amount(), matrix); | |
553 image_filter = CreateMatrixImageFilter(matrix, image_filter); | |
554 break; | |
555 case FilterOperation::SEPIA: | |
556 GetSepiaMatrix(1 - op.amount(), matrix); | |
557 image_filter = CreateMatrixImageFilter(matrix, image_filter); | |
558 break; | |
559 case FilterOperation::SATURATE: | |
560 GetSaturateMatrix(op.amount(), matrix); | |
561 image_filter = CreateMatrixImageFilter(matrix, image_filter); | |
562 break; | |
563 case FilterOperation::HUE_ROTATE: | |
564 GetHueRotateMatrix(op.amount(), matrix); | |
565 image_filter = CreateMatrixImageFilter(matrix, image_filter); | |
566 break; | |
567 case FilterOperation::INVERT: | |
568 GetInvertMatrix(op.amount(), matrix); | |
569 image_filter = CreateMatrixImageFilter(matrix, image_filter); | |
570 break; | |
571 case FilterOperation::OPACITY: | |
572 GetOpacityMatrix(op.amount(), matrix); | |
573 image_filter = CreateMatrixImageFilter(matrix, image_filter); | |
574 break; | |
575 case FilterOperation::BRIGHTNESS: | |
576 GetBrightnessMatrix(op.amount(), matrix); | |
577 image_filter = CreateMatrixImageFilter(matrix, image_filter); | |
578 break; | |
579 case FilterOperation::CONTRAST: | |
580 GetContrastMatrix(op.amount(), matrix); | |
581 image_filter = CreateMatrixImageFilter(matrix, image_filter); | |
582 break; | |
583 case FilterOperation::BLUR: | |
584 image_filter = skia::AdoptRef(new SkBlurImageFilter( | |
585 op.amount(), op.amount(), image_filter.get())); | |
586 break; | |
587 case FilterOperation::DROP_SHADOW: | |
588 image_filter = skia::AdoptRef(new DropShadowImageFilter( | |
589 SkIntToScalar(op.drop_shadow_offset().x()), | |
590 SkIntToScalar(op.drop_shadow_offset().y()), | |
591 SkIntToScalar(op.amount()), | |
592 op.drop_shadow_color(), | |
593 image_filter.get())); | |
594 break; | |
595 case FilterOperation::COLOR_MATRIX: | |
596 image_filter = CreateMatrixImageFilter(op.matrix(), image_filter); | |
597 break; | |
598 case FilterOperation::ZOOM: | |
599 // TODO(ajuma): Add support for this. Note that zoom filter operations | |
600 // are only used for background filters right now. | |
ajuma
2013/07/31 18:40:37
Is this worth doing? That is, are there any plans
Stephen White
2013/07/31 19:18:51
Check with zork@ about this filter; I think it's o
ajuma
2013/09/09 17:35:36
I've added the code that was missing here for ZOOM
| |
601 NOTREACHED(); | |
602 case FilterOperation::SATURATING_BRIGHTNESS: | |
603 GetSaturatingBrightnessMatrix(op.amount(), matrix); | |
604 image_filter = CreateMatrixImageFilter(matrix, image_filter); | |
605 break; | |
606 case FilterOperation::REFERENCE: { | |
607 skia::RefPtr<SkColorFilter> cf; | |
608 | |
609 { | |
610 SkColorFilter* colorfilter_rawptr = NULL; | |
611 op.image_filter()->asColorFilter(&colorfilter_rawptr); | |
612 cf = skia::AdoptRef(colorfilter_rawptr); | |
613 } | |
614 | |
615 if (cf && cf->asColorMatrix(matrix) && | |
616 !op.image_filter()->getInput(0)) { | |
617 image_filter = CreateMatrixImageFilter(matrix, image_filter); | |
618 } else if (image_filter.get()) { | |
619 image_filter = skia::AdoptRef(new SkComposeImageFilter( | |
620 op.image_filter().get(), image_filter.get())); | |
ajuma
2013/07/31 18:40:37
The plan is to use a no-op filter as the SourceGra
Stephen White
2013/07/31 19:18:51
That seems reasonable. I like the use of the SkCom
| |
621 } else { | |
622 image_filter = op.image_filter(); | |
623 } | |
624 break; | |
625 } | |
626 } | |
627 } | |
628 return image_filter; | |
629 } | |
630 | |
462 } // namespace cc | 631 } // namespace cc |
OLD | NEW |