diff --git a/cc/cc_tests.gyp b/cc/cc_tests.gyp index a5e60dd5904fc0..7d96d4cf1977cb 100644 --- a/cc/cc_tests.gyp +++ b/cc/cc_tests.gyp @@ -46,7 +46,6 @@ 'output/gl_renderer_unittest.cc', 'output/output_surface_unittest.cc', 'output/renderer_pixeltest.cc', - 'output/render_surface_filters_unittest.cc', 'output/shader_unittest.cc', 'output/software_renderer_unittest.cc', 'quads/draw_quad_unittest.cc', diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc index 68fb4566c4a553..04c1158d3b10d0 100644 --- a/cc/output/gl_renderer.cc +++ b/cc/output/gl_renderer.cc @@ -478,46 +478,6 @@ void GLRenderer::DrawDebugBorderQuad(const DrawingFrame* frame, Context()->drawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_SHORT, 0)); } -static inline SkBitmap ApplyFilters(GLRenderer* renderer, - ContextProvider* offscreen_contexts, - const FilterOperations& filters, - ScopedResource* source_texture_resource) { - if (filters.IsEmpty()) - return SkBitmap(); - - if (!offscreen_contexts || !offscreen_contexts->GrContext()) - return SkBitmap(); - - ResourceProvider::ScopedWriteLockGL lock(renderer->resource_provider(), - source_texture_resource->id()); - - // Flush the compositor context to ensure that textures there are available - // in the shared context. Do this after locking/creating the compositor - // texture. - renderer->resource_provider()->Flush(); - - // Make sure skia uses the correct GL context. - offscreen_contexts->Context3d()->makeContextCurrent(); - - SkBitmap source = - RenderSurfaceFilters::Apply(filters, - lock.texture_id(), - source_texture_resource->size(), - offscreen_contexts->GrContext()); - - // Flush skia context so that all the rendered stuff appears on the - // texture. - offscreen_contexts->GrContext()->flush(); - - // Flush the GL context so rendering results from this context are - // visible in the compositor's context. - offscreen_contexts->Context3d()->flush(); - - // Use the compositor's GL context again. - renderer->Context()->makeContextCurrent(); - return source; -} - static SkBitmap ApplyImageFilter(GLRenderer* renderer, ContextProvider* offscreen_contexts, gfx::Point origin, @@ -631,10 +591,6 @@ scoped_ptr GLRenderer::DrawBackgroundFilters( // TODO(danakj): When this algorithm changes, update // LayerTreeHost::PrioritizeTextures() accordingly. - FilterOperations filters = - RenderSurfaceFilters::Optimize(quad->background_filters); - DCHECK(!filters.IsEmpty()); - // TODO(danakj): We only allow background filters on an opaque render surface // because other surfaces may contain translucent pixels, and the contents // behind those translucent pixels wouldn't have the filter applied. @@ -642,13 +598,18 @@ scoped_ptr GLRenderer::DrawBackgroundFilters( return scoped_ptr(); DCHECK(!frame->current_texture); + // TODO(ajuma): Add support for reference filters once + // FilterOperations::GetOutsets supports reference filters. + if (quad->background_filters.HasReferenceFilter()) + return scoped_ptr(); + // TODO(danakj): Do a single readback for both the surface and replica and // cache the filtered results (once filter textures are not reused). gfx::Rect window_rect = gfx::ToEnclosingRect(MathUtil::MapClippedRect( contents_device_transform, SharedGeometryQuad().BoundingBox())); int top, right, bottom, left; - filters.GetOutsets(&top, &right, &bottom, &left); + quad->background_filters.GetOutsets(&top, &right, &bottom, &left); window_rect.Inset(-left, -top, -right, -bottom); window_rect.Intersect( @@ -668,11 +629,15 @@ scoped_ptr GLRenderer::DrawBackgroundFilters( window_rect); } + skia::RefPtr filter = RenderSurfaceFilters::BuildImageFilter( + quad->background_filters, device_background_texture->size()); + SkBitmap filtered_device_background = - ApplyFilters(this, - frame->offscreen_context_provider, - filters, - device_background_texture.get()); + ApplyImageFilter(this, + frame->offscreen_context_provider, + quad->rect.origin(), + filter.get(), + device_background_texture.get()); if (!filtered_device_background.getTexture()) return scoped_ptr(); @@ -774,7 +739,7 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, bool use_color_matrix = false; // TODO(ajuma): Always use RenderSurfaceFilters::BuildImageFilter, not just // when we have a reference filter. - if (quad->filters.HasReferenceFilter()) { + if (!quad->filters.IsEmpty()) { skia::RefPtr filter = RenderSurfaceFilters::BuildImageFilter( quad->filters, contents_texture->size()); if (filter) { @@ -798,21 +763,6 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, contents_texture); } } - } else if (!quad->filters.IsEmpty()) { - FilterOperations optimized_filters = - RenderSurfaceFilters::Optimize(quad->filters); - - if ((optimized_filters.size() == 1) && - (optimized_filters.at(0).type() == FilterOperation::COLOR_MATRIX)) { - memcpy( - color_matrix, optimized_filters.at(0).matrix(), sizeof(color_matrix)); - use_color_matrix = true; - } else { - filter_bitmap = ApplyFilters(this, - frame->offscreen_context_provider, - optimized_filters, - contents_texture); - } } // Draw the background texture if there is one. diff --git a/cc/output/render_surface_filters.cc b/cc/output/render_surface_filters.cc index fe9959e8e26ce5..e10ea885e7feea 100644 --- a/cc/output/render_surface_filters.cc +++ b/cc/output/render_surface_filters.cc @@ -147,100 +147,6 @@ void GetSepiaMatrix(float amount, SkScalar matrix[20]) { matrix[18] = 1.f; } -// The 5x4 matrix is really a "compressed" version of a 5x5 matrix that'd have -// (0 0 0 0 1) as a last row, and that would be applied to a 5-vector extended -// from the 4-vector color with a 1. -void MultColorMatrix(SkScalar a[20], SkScalar b[20], SkScalar out[20]) { - for (int j = 0; j < 4; ++j) { - for (int i = 0; i < 5; ++i) { - out[i+j*5] = i == 4 ? a[4+j*5] : 0.f; - for (int k = 0; k < 4; ++k) - out[i+j*5] += a[k+j*5] * b[i+k*5]; - } - } -} - -// To detect if we need to apply clamping after applying a matrix, we check if -// any output component might go outside of [0, 255] for any combination of -// input components in [0..255]. -// Each output component is an affine transformation of the input component, so -// the minimum and maximum values are for any combination of minimum or maximum -// values of input components (i.e. 0 or 255). -// E.g. if R' = x*R + y*G + z*B + w*A + t -// Then the maximum value will be for R=255 if x>0 or R=0 if x<0, and the -// minimum value will be for R=0 if x>0 or R=255 if x<0. -// Same goes for all components. -bool ComponentNeedsClamping(SkScalar row[5]) { - SkScalar max_value = row[4] / 255.f; - SkScalar min_value = row[4] / 255.f; - for (int i = 0; i < 4; ++i) { - if (row[i] > 0) - max_value += row[i]; - else - min_value += row[i]; - } - return (max_value > 1.f) || (min_value < 0.f); -} - -bool MatrixNeedsClamping(SkScalar matrix[20]) { - return ComponentNeedsClamping(matrix) - || ComponentNeedsClamping(matrix+5) - || ComponentNeedsClamping(matrix+10) - || ComponentNeedsClamping(matrix+15); -} - -bool GetColorMatrix(const FilterOperation& op, SkScalar matrix[20]) { - switch (op.type()) { - case FilterOperation::BRIGHTNESS: { - GetBrightnessMatrix(op.amount(), matrix); - return true; - } - case FilterOperation::SATURATING_BRIGHTNESS: { - GetSaturatingBrightnessMatrix(op.amount(), matrix); - return true; - } - case FilterOperation::CONTRAST: { - GetContrastMatrix(op.amount(), matrix); - return true; - } - case FilterOperation::GRAYSCALE: { - GetGrayscaleMatrix(1.f - op.amount(), matrix); - return true; - } - case FilterOperation::SEPIA: { - GetSepiaMatrix(1.f - op.amount(), matrix); - return true; - } - case FilterOperation::SATURATE: { - GetSaturateMatrix(op.amount(), matrix); - return true; - } - case FilterOperation::HUE_ROTATE: { - GetHueRotateMatrix(op.amount(), matrix); - return true; - } - case FilterOperation::INVERT: { - GetInvertMatrix(op.amount(), matrix); - return true; - } - case FilterOperation::OPACITY: { - GetOpacityMatrix(op.amount(), matrix); - return true; - } - case FilterOperation::COLOR_MATRIX: { - memcpy(matrix, op.matrix(), sizeof(SkScalar[20])); - return true; - } - case FilterOperation::BLUR: - case FilterOperation::DROP_SHADOW: - case FilterOperation::ZOOM: - case FilterOperation::REFERENCE: - return false; - } - NOTREACHED(); - return false; -} - skia::RefPtr CreateMatrixImageFilter( const SkScalar matrix[20], const skia::RefPtr& input) { @@ -250,238 +156,8 @@ skia::RefPtr CreateMatrixImageFilter( SkColorFilterImageFilter::Create(color_filter.get(), input.get())); } -class FilterBufferState { - public: - FilterBufferState(GrContext* gr_context, - gfx::SizeF size, - unsigned texture_id) - : gr_context_(gr_context), - current_texture_(0) { - // Wrap the source texture in a Ganesh platform texture. - GrBackendTextureDesc backend_texture_description; - backend_texture_description.fWidth = size.width(); - backend_texture_description.fHeight = size.height(); - backend_texture_description.fConfig = kSkia8888_GrPixelConfig; - backend_texture_description.fTextureHandle = texture_id; - skia::RefPtr texture = skia::AdoptRef( - gr_context->wrapBackendTexture(backend_texture_description)); - // Place the platform texture inside an SkBitmap. - source_.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height()); - skia::RefPtr pixel_ref = - skia::AdoptRef(new SkGrPixelRef(texture.get())); - source_.setPixelRef(pixel_ref.get()); - } - - ~FilterBufferState() {} - - bool Init(int filter_count) { - int scratch_count = std::min(2, filter_count); - GrTextureDesc desc; - desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit; - desc.fSampleCnt = 0; - desc.fWidth = source_.width(); - desc.fHeight = source_.height(); - desc.fConfig = kSkia8888_GrPixelConfig; - for (int i = 0; i < scratch_count; ++i) { - GrAutoScratchTexture scratch_texture( - gr_context_, desc, GrContext::kExact_ScratchTexMatch); - scratch_textures_[i] = skia::AdoptRef(scratch_texture.detach()); - if (!scratch_textures_[i]) - return false; - } - return true; - } - - SkCanvas* Canvas() { - if (!canvas_) - CreateCanvas(); - return canvas_.get(); - } - - const SkBitmap& Source() { return source_; } - - void Swap() { - canvas_->flush(); - canvas_.clear(); - device_.clear(); - - skia::RefPtr pixel_ref = skia::AdoptRef( - new SkGrPixelRef(scratch_textures_[current_texture_].get())); - source_.setPixelRef(pixel_ref.get()); - current_texture_ = 1 - current_texture_; - } - - private: - void CreateCanvas() { - DCHECK(scratch_textures_[current_texture_].get()); - device_ = skia::AdoptRef(new SkGpuDevice( - gr_context_, scratch_textures_[current_texture_].get())); - canvas_ = skia::AdoptRef(new SkCanvas(device_.get())); - canvas_->clear(0x0); - } - - GrContext* gr_context_; - SkBitmap source_; - skia::RefPtr scratch_textures_[2]; - int current_texture_; - skia::RefPtr device_; - skia::RefPtr canvas_; -}; - } // namespace -FilterOperations RenderSurfaceFilters::Optimize( - const FilterOperations& filters) { - FilterOperations new_list; - - SkScalar accumulated_color_matrix[20]; - bool have_accumulated_color_matrix = false; - for (unsigned i = 0; i < filters.size(); ++i) { - const FilterOperation& op = filters.at(i); - - // If the filter is a color matrix, we may be able to combine it with - // following Filter(s) that also are color matrices. - SkScalar matrix[20]; - if (GetColorMatrix(op, matrix)) { - if (have_accumulated_color_matrix) { - SkScalar new_matrix[20]; - MultColorMatrix(matrix, accumulated_color_matrix, new_matrix); - memcpy(accumulated_color_matrix, - new_matrix, - sizeof(accumulated_color_matrix)); - } else { - memcpy(accumulated_color_matrix, - matrix, - sizeof(accumulated_color_matrix)); - have_accumulated_color_matrix = true; - } - - // We can only combine matrices if clamping of color components - // would have no effect. - if (!MatrixNeedsClamping(accumulated_color_matrix)) - continue; - } - - if (have_accumulated_color_matrix) { - new_list.Append(FilterOperation::CreateColorMatrixFilter( - accumulated_color_matrix)); - } - have_accumulated_color_matrix = false; - - switch (op.type()) { - case FilterOperation::BLUR: - case FilterOperation::DROP_SHADOW: - 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: - case FilterOperation::GRAYSCALE: - case FilterOperation::SEPIA: - case FilterOperation::SATURATE: - case FilterOperation::HUE_ROTATE: - case FilterOperation::INVERT: - case FilterOperation::OPACITY: - case FilterOperation::COLOR_MATRIX: - break; - } - } - if (have_accumulated_color_matrix) { - new_list.Append(FilterOperation::CreateColorMatrixFilter( - accumulated_color_matrix)); - } - return new_list; -} - -SkBitmap RenderSurfaceFilters::Apply(const FilterOperations& filters, - unsigned texture_id, - gfx::SizeF size, - GrContext* gr_context) { - DCHECK(gr_context); - - FilterBufferState state(gr_context, size, texture_id); - if (!state.Init(filters.size())) - return SkBitmap(); - - for (unsigned i = 0; i < filters.size(); ++i) { - const FilterOperation& op = filters.at(i); - SkCanvas* canvas = state.Canvas(); - switch (op.type()) { - case FilterOperation::COLOR_MATRIX: { - SkPaint paint; - skia::RefPtr filter = - skia::AdoptRef(new SkColorMatrixFilter(op.matrix())); - paint.setColorFilter(filter.get()); - canvas->drawBitmap(state.Source(), 0, 0, &paint); - break; - } - case FilterOperation::BLUR: { - float std_deviation = op.amount(); - skia::RefPtr filter = - skia::AdoptRef(new SkBlurImageFilter(std_deviation, std_deviation)); - SkPaint paint; - paint.setImageFilter(filter.get()); - canvas->drawSprite(state.Source(), 0, 0, &paint); - break; - } - case FilterOperation::DROP_SHADOW: { - skia::RefPtr blur_filter = - skia::AdoptRef(new SkBlurImageFilter(op.amount(), op.amount())); - skia::RefPtr color_filter = - skia::AdoptRef(SkColorFilter::CreateModeFilter( - op.drop_shadow_color(), SkXfermode::kSrcIn_Mode)); - SkPaint paint; - paint.setImageFilter(blur_filter.get()); - paint.setColorFilter(color_filter.get()); - paint.setXfermodeMode(SkXfermode::kSrcOver_Mode); - canvas->saveLayer(NULL, &paint); - canvas->drawBitmap(state.Source(), - op.drop_shadow_offset().x(), - op.drop_shadow_offset().y()); - canvas->restore(); - canvas->drawBitmap(state.Source(), 0, 0); - break; - } - case FilterOperation::ZOOM: { - SkPaint paint; - int width = state.Source().width(); - int height = state.Source().height(); - skia::RefPtr zoom_filter = skia::AdoptRef( - new SkMagnifierImageFilter( - SkRect::MakeXYWH( - (width - (width / op.amount())) / 2.f, - (height - (height / op.amount())) / 2.f, - width / op.amount(), - height / op.amount()), - op.zoom_inset())); - paint.setImageFilter(zoom_filter.get()); - canvas->saveLayer(NULL, &paint); - canvas->drawBitmap(state.Source(), 0, 0); - canvas->restore(); - break; - } - case FilterOperation::REFERENCE: - case FilterOperation::BRIGHTNESS: - case FilterOperation::SATURATING_BRIGHTNESS: - case FilterOperation::CONTRAST: - case FilterOperation::GRAYSCALE: - case FilterOperation::SEPIA: - case FilterOperation::SATURATE: - case FilterOperation::HUE_ROTATE: - case FilterOperation::INVERT: - case FilterOperation::OPACITY: - NOTREACHED(); - break; - } - state.Swap(); - } - return state.Source(); -} - skia::RefPtr RenderSurfaceFilters::BuildImageFilter( const FilterOperations& filters, gfx::SizeF size) { diff --git a/cc/output/render_surface_filters_unittest.cc b/cc/output/render_surface_filters_unittest.cc deleted file mode 100644 index 38c6cc343b16a0..00000000000000 --- a/cc/output/render_surface_filters_unittest.cc +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "cc/output/render_surface_filters.h" - -#include "cc/output/filter_operation.h" -#include "cc/output/filter_operations.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace cc { -namespace { - -// Checks whether op can be combined with a following color matrix. -bool IsCombined(const FilterOperation& op) { - FilterOperations filters; - filters.Append(op); - // brightness(0.0f) is identity. - filters.Append(FilterOperation::CreateBrightnessFilter(0.0f)); - FilterOperations optimized = RenderSurfaceFilters::Optimize(filters); - return optimized.size() == 1; -} - -TEST(RenderSurfaceFiltersTest, TestColorMatrixFiltersCombined) { - // Several filters should always combine for any amount between 0 and 1: - // grayscale, saturate, invert, contrast, opacity. - EXPECT_TRUE(IsCombined(FilterOperation::CreateGrayscaleFilter(0.0f))); - // Note that we use 0.3f to avoid "argument is truncated from 'double' to - // 'float'" warnings on Windows. 0.5f is exactly representable as a float, so - // there is no warning. - EXPECT_TRUE(IsCombined(FilterOperation::CreateGrayscaleFilter(0.3f))); - EXPECT_TRUE(IsCombined(FilterOperation::CreateGrayscaleFilter(0.5f))); - EXPECT_TRUE(IsCombined(FilterOperation::CreateGrayscaleFilter(1.0f))); - - EXPECT_TRUE(IsCombined(FilterOperation::CreateSaturateFilter(0.0f))); - EXPECT_TRUE(IsCombined(FilterOperation::CreateSaturateFilter(0.3f))); - EXPECT_TRUE(IsCombined(FilterOperation::CreateSaturateFilter(0.5))); - EXPECT_TRUE(IsCombined(FilterOperation::CreateSaturateFilter(1.0f))); - - EXPECT_TRUE(IsCombined(FilterOperation::CreateInvertFilter(0.0f))); - EXPECT_TRUE(IsCombined(FilterOperation::CreateInvertFilter(0.3f))); - EXPECT_TRUE(IsCombined(FilterOperation::CreateInvertFilter(0.5))); - EXPECT_TRUE(IsCombined(FilterOperation::CreateInvertFilter(1.0f))); - - EXPECT_TRUE(IsCombined(FilterOperation::CreateContrastFilter(0.0f))); - EXPECT_TRUE(IsCombined(FilterOperation::CreateContrastFilter(0.3f))); - EXPECT_TRUE(IsCombined(FilterOperation::CreateContrastFilter(0.5))); - EXPECT_TRUE(IsCombined(FilterOperation::CreateContrastFilter(1.0f))); - - EXPECT_TRUE(IsCombined(FilterOperation::CreateOpacityFilter(0.0f))); - EXPECT_TRUE(IsCombined(FilterOperation::CreateOpacityFilter(0.3f))); - EXPECT_TRUE(IsCombined(FilterOperation::CreateOpacityFilter(0.5))); - EXPECT_TRUE(IsCombined(FilterOperation::CreateOpacityFilter(1.0f))); - - // Brightness combines when amount <= 1 - EXPECT_TRUE(IsCombined(FilterOperation::CreateBrightnessFilter(0.5))); - EXPECT_TRUE(IsCombined(FilterOperation::CreateBrightnessFilter(1.0f))); - EXPECT_FALSE(IsCombined(FilterOperation::CreateBrightnessFilter(1.5))); - - // SaturatingBrightness combines only when amount == 0 - EXPECT_TRUE( - IsCombined(FilterOperation::CreateSaturatingBrightnessFilter(0.0f))); - EXPECT_FALSE( - IsCombined(FilterOperation::CreateSaturatingBrightnessFilter(0.5))); - EXPECT_FALSE( - IsCombined(FilterOperation::CreateSaturatingBrightnessFilter(1.0f))); - - // Several filters should never combine: blur, drop-shadow. - EXPECT_FALSE(IsCombined(FilterOperation::CreateBlurFilter(3.0f))); - EXPECT_FALSE(IsCombined(FilterOperation::CreateDropShadowFilter( - gfx::Point(2, 2), 3.0f, 0xffffffff))); - - // sepia and hue may or may not combine depending on the value. - EXPECT_TRUE(IsCombined(FilterOperation::CreateSepiaFilter(0.0f))); - EXPECT_FALSE(IsCombined(FilterOperation::CreateSepiaFilter(1.0f))); - EXPECT_TRUE(IsCombined(FilterOperation::CreateHueRotateFilter(0.0f))); - EXPECT_FALSE(IsCombined(FilterOperation::CreateHueRotateFilter(180.0f))); - - float matrix1[20] = { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, }; - EXPECT_TRUE(IsCombined(FilterOperation::CreateColorMatrixFilter(matrix1))); - - float matrix2[20] = { 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, }; - EXPECT_FALSE( - IsCombined(FilterOperation::CreateColorMatrixFilter(matrix2))); - - float matrix3[20] = { 0.25f, 0.0f, 0.0f, 0.0f, 255.0f * 0.75f, - 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, }; - EXPECT_TRUE(IsCombined(FilterOperation::CreateColorMatrixFilter(matrix3))); - - float matrix4[20] = { -0.25f, 0.75f, 0.0f, 0.0f, 255.0f * 0.25f, - 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, }; - EXPECT_TRUE(IsCombined(FilterOperation::CreateColorMatrixFilter(matrix4))); -} - -TEST(RenderSurfaceFiltersTest, TestOptimize) { - FilterOperation combines(FilterOperation::CreateBrightnessFilter(1.0f)); - FilterOperation doesnt_combine( - FilterOperation::CreateBrightnessFilter(1.5f)); - - FilterOperations filters; - FilterOperations optimized = RenderSurfaceFilters::Optimize(filters); - EXPECT_EQ(0u, optimized.size()); - - filters.Append(combines); - optimized = RenderSurfaceFilters::Optimize(filters); - EXPECT_EQ(1u, optimized.size()); - - filters.Append(combines); - optimized = RenderSurfaceFilters::Optimize(filters); - EXPECT_EQ(1u, optimized.size()); - - filters.Append(doesnt_combine); - optimized = RenderSurfaceFilters::Optimize(filters); - EXPECT_EQ(1u, optimized.size()); - - filters.Append(combines); - optimized = RenderSurfaceFilters::Optimize(filters); - EXPECT_EQ(2u, optimized.size()); - - filters.Append(doesnt_combine); - optimized = RenderSurfaceFilters::Optimize(filters); - EXPECT_EQ(2u, optimized.size()); - - filters.Append(doesnt_combine); - optimized = RenderSurfaceFilters::Optimize(filters); - EXPECT_EQ(3u, optimized.size()); -} - -} // namespace -} // namespace cc