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

Side by Side Diff: cc/output/render_surface_filters.cc

Issue 21154002: Add support for converting cc::FilterOperations into an SkImageFilter (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 4 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 // 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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698