| Index: cc/output/render_surface_filters.cc
 | 
| diff --git a/cc/output/render_surface_filters.cc b/cc/output/render_surface_filters.cc
 | 
| index 04d8c5ab9f743c4c4e6b67bb902fb27e94a2af4f..fe9959e8e26ce5d94c2004e014de29a1ccf94487 100644
 | 
| --- a/cc/output/render_surface_filters.cc
 | 
| +++ b/cc/output/render_surface_filters.cc
 | 
| @@ -11,8 +11,13 @@
 | 
|  #include "cc/output/filter_operations.h"
 | 
|  #include "skia/ext/refptr.h"
 | 
|  #include "third_party/skia/include/core/SkCanvas.h"
 | 
| +#include "third_party/skia/include/core/SkFlattenableBuffers.h"
 | 
| +#include "third_party/skia/include/core/SkImageFilter.h"
 | 
|  #include "third_party/skia/include/effects/SkBlurImageFilter.h"
 | 
| +#include "third_party/skia/include/effects/SkColorFilterImageFilter.h"
 | 
|  #include "third_party/skia/include/effects/SkColorMatrixFilter.h"
 | 
| +#include "third_party/skia/include/effects/SkComposeImageFilter.h"
 | 
| +#include "third_party/skia/include/effects/SkDropShadowImageFilter.h"
 | 
|  #include "third_party/skia/include/effects/SkMagnifierImageFilter.h"
 | 
|  #include "third_party/skia/include/gpu/SkGpuDevice.h"
 | 
|  #include "third_party/skia/include/gpu/SkGrPixelRef.h"
 | 
| @@ -229,12 +234,22 @@ bool GetColorMatrix(const FilterOperation& op, SkScalar matrix[20]) {
 | 
|      case FilterOperation::BLUR:
 | 
|      case FilterOperation::DROP_SHADOW:
 | 
|      case FilterOperation::ZOOM:
 | 
| +    case FilterOperation::REFERENCE:
 | 
|        return false;
 | 
|    }
 | 
|    NOTREACHED();
 | 
|    return false;
 | 
|  }
 | 
|  
 | 
| +skia::RefPtr<SkImageFilter> CreateMatrixImageFilter(
 | 
| +    const SkScalar matrix[20],
 | 
| +    const skia::RefPtr<SkImageFilter>& input) {
 | 
| +  skia::RefPtr<SkColorFilter> color_filter =
 | 
| +      skia::AdoptRef(new SkColorMatrixFilter(matrix));
 | 
| +  return skia::AdoptRef(
 | 
| +      SkColorFilterImageFilter::Create(color_filter.get(), input.get()));
 | 
| +}
 | 
| +
 | 
|  class FilterBufferState {
 | 
|   public:
 | 
|    FilterBufferState(GrContext* gr_context,
 | 
| @@ -359,6 +374,9 @@ FilterOperations RenderSurfaceFilters::Optimize(
 | 
|        case FilterOperation::ZOOM:
 | 
|          new_list.Append(op);
 | 
|          break;
 | 
| +      case FilterOperation::REFERENCE:
 | 
| +        // Not supported on this code path.
 | 
| +        NOTREACHED();
 | 
|        case FilterOperation::BRIGHTNESS:
 | 
|        case FilterOperation::SATURATING_BRIGHTNESS:
 | 
|        case FilterOperation::CONTRAST:
 | 
| @@ -446,6 +464,7 @@ SkBitmap RenderSurfaceFilters::Apply(const FilterOperations& filters,
 | 
|          canvas->restore();
 | 
|          break;
 | 
|        }
 | 
| +      case FilterOperation::REFERENCE:
 | 
|        case FilterOperation::BRIGHTNESS:
 | 
|        case FilterOperation::SATURATING_BRIGHTNESS:
 | 
|        case FilterOperation::CONTRAST:
 | 
| @@ -463,4 +482,111 @@ SkBitmap RenderSurfaceFilters::Apply(const FilterOperations& filters,
 | 
|    return state.Source();
 | 
|  }
 | 
|  
 | 
| +skia::RefPtr<SkImageFilter> RenderSurfaceFilters::BuildImageFilter(
 | 
| +    const FilterOperations& filters,
 | 
| +    gfx::SizeF size) {
 | 
| +  skia::RefPtr<SkImageFilter> image_filter;
 | 
| +  SkScalar matrix[20];
 | 
| +  for (size_t i = 0; i < filters.size(); ++i) {
 | 
| +    const FilterOperation& op = filters.at(i);
 | 
| +    switch (op.type()) {
 | 
| +      case FilterOperation::GRAYSCALE:
 | 
| +        GetGrayscaleMatrix(1.f - op.amount(), matrix);
 | 
| +        image_filter = CreateMatrixImageFilter(matrix, image_filter);
 | 
| +        break;
 | 
| +      case FilterOperation::SEPIA:
 | 
| +        GetSepiaMatrix(1.f - op.amount(), matrix);
 | 
| +        image_filter = CreateMatrixImageFilter(matrix, image_filter);
 | 
| +        break;
 | 
| +      case FilterOperation::SATURATE:
 | 
| +        GetSaturateMatrix(op.amount(), matrix);
 | 
| +        image_filter = CreateMatrixImageFilter(matrix, image_filter);
 | 
| +        break;
 | 
| +      case FilterOperation::HUE_ROTATE:
 | 
| +        GetHueRotateMatrix(op.amount(), matrix);
 | 
| +        image_filter = CreateMatrixImageFilter(matrix, image_filter);
 | 
| +        break;
 | 
| +      case FilterOperation::INVERT:
 | 
| +        GetInvertMatrix(op.amount(), matrix);
 | 
| +        image_filter = CreateMatrixImageFilter(matrix, image_filter);
 | 
| +        break;
 | 
| +      case FilterOperation::OPACITY:
 | 
| +        GetOpacityMatrix(op.amount(), matrix);
 | 
| +        image_filter = CreateMatrixImageFilter(matrix, image_filter);
 | 
| +        break;
 | 
| +      case FilterOperation::BRIGHTNESS:
 | 
| +        GetBrightnessMatrix(op.amount(), matrix);
 | 
| +        image_filter = CreateMatrixImageFilter(matrix, image_filter);
 | 
| +        break;
 | 
| +      case FilterOperation::CONTRAST:
 | 
| +        GetContrastMatrix(op.amount(), matrix);
 | 
| +        image_filter = CreateMatrixImageFilter(matrix, image_filter);
 | 
| +        break;
 | 
| +      case FilterOperation::BLUR:
 | 
| +        image_filter = skia::AdoptRef(new SkBlurImageFilter(
 | 
| +            op.amount(), op.amount(), image_filter.get()));
 | 
| +        break;
 | 
| +      case FilterOperation::DROP_SHADOW:
 | 
| +        image_filter = skia::AdoptRef(new SkDropShadowImageFilter(
 | 
| +            SkIntToScalar(op.drop_shadow_offset().x()),
 | 
| +            SkIntToScalar(op.drop_shadow_offset().y()),
 | 
| +            SkIntToScalar(op.amount()),
 | 
| +            op.drop_shadow_color(),
 | 
| +            image_filter.get()));
 | 
| +        break;
 | 
| +      case FilterOperation::COLOR_MATRIX:
 | 
| +        image_filter = CreateMatrixImageFilter(op.matrix(), image_filter);
 | 
| +        break;
 | 
| +      case FilterOperation::ZOOM: {
 | 
| +        skia::RefPtr<SkImageFilter> zoom_filter = skia::AdoptRef(
 | 
| +            new SkMagnifierImageFilter(
 | 
| +                SkRect::MakeXYWH(
 | 
| +                    (size.width() - (size.width() / op.amount())) / 2.f,
 | 
| +                    (size.height() - (size.height() / op.amount())) / 2.f,
 | 
| +                    size.width() / op.amount(),
 | 
| +                    size.height() / op.amount()),
 | 
| +                op.zoom_inset()));
 | 
| +        if (image_filter.get()) {
 | 
| +          // TODO(ajuma): When there's a 1-input version of
 | 
| +          // SkMagnifierImageFilter, use that to handle the input filter
 | 
| +          // instead of using an SkComposeImageFilter.
 | 
| +          image_filter = skia::AdoptRef(new SkComposeImageFilter(
 | 
| +              zoom_filter.get(), image_filter.get()));
 | 
| +        } else {
 | 
| +          image_filter = zoom_filter;
 | 
| +        }
 | 
| +        break;
 | 
| +      }
 | 
| +      case FilterOperation::SATURATING_BRIGHTNESS:
 | 
| +        GetSaturatingBrightnessMatrix(op.amount(), matrix);
 | 
| +        image_filter = CreateMatrixImageFilter(matrix, image_filter);
 | 
| +        break;
 | 
| +      case FilterOperation::REFERENCE: {
 | 
| +        if (!op.image_filter())
 | 
| +          break;
 | 
| +
 | 
| +        skia::RefPtr<SkColorFilter> cf;
 | 
| +
 | 
| +        {
 | 
| +          SkColorFilter* colorfilter_rawptr = NULL;
 | 
| +          op.image_filter()->asColorFilter(&colorfilter_rawptr);
 | 
| +          cf = skia::AdoptRef(colorfilter_rawptr);
 | 
| +        }
 | 
| +
 | 
| +        if (cf && cf->asColorMatrix(matrix) &&
 | 
| +            !op.image_filter()->getInput(0)) {
 | 
| +          image_filter = CreateMatrixImageFilter(matrix, image_filter);
 | 
| +        } else if (image_filter) {
 | 
| +          image_filter = skia::AdoptRef(new SkComposeImageFilter(
 | 
| +              op.image_filter().get(), image_filter.get()));
 | 
| +        } else {
 | 
| +          image_filter = op.image_filter();
 | 
| +        }
 | 
| +        break;
 | 
| +      }
 | 
| +    }
 | 
| +  }
 | 
| +  return image_filter;
 | 
| +}
 | 
| +
 | 
|  }  // namespace cc
 | 
| 
 |