diff options
author | achaulk <achaulk@chromium.org> | 2015-04-01 10:26:08 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-04-01 17:27:23 +0000 |
commit | f47b494165f7d03a8e92b1780acdf673a87cb454 (patch) | |
tree | 3c4f699bb048b95187abd58c157fad35cbe18020 | |
parent | 9684384a5c73aaacf640d565039ad7357ee6d8da (diff) | |
download | chromium_src-f47b494165f7d03a8e92b1780acdf673a87cb454.zip chromium_src-f47b494165f7d03a8e92b1780acdf673a87cb454.tar.gz chromium_src-f47b494165f7d03a8e92b1780acdf673a87cb454.tar.bz2 |
Add underlays and split off common overlay functionality
Review URL: https://codereview.chromium.org/979693005
Cr-Commit-Position: refs/heads/master@{#323274}
-rw-r--r-- | cc/BUILD.gn | 4 | ||||
-rw-r--r-- | cc/cc.gyp | 4 | ||||
-rw-r--r-- | cc/output/overlay_strategy_common.cc | 135 | ||||
-rw-r--r-- | cc/output/overlay_strategy_common.h | 49 | ||||
-rw-r--r-- | cc/output/overlay_strategy_single_on_top.cc | 119 | ||||
-rw-r--r-- | cc/output/overlay_strategy_single_on_top.h | 19 | ||||
-rw-r--r-- | cc/output/overlay_strategy_underlay.cc | 69 | ||||
-rw-r--r-- | cc/output/overlay_strategy_underlay.h | 32 | ||||
-rw-r--r-- | cc/output/overlay_unittest.cc | 89 | ||||
-rw-r--r-- | cc/quads/list_container.h | 6 | ||||
-rw-r--r-- | cc/quads/list_container_unittest.cc | 52 |
11 files changed, 412 insertions, 166 deletions
diff --git a/cc/BUILD.gn b/cc/BUILD.gn index 2d4a393..ee83aec 100644 --- a/cc/BUILD.gn +++ b/cc/BUILD.gn @@ -248,8 +248,12 @@ component("cc") { "output/overlay_candidate_validator.h", "output/overlay_processor.cc", "output/overlay_processor.h", + "output/overlay_strategy_common.cc", + "output/overlay_strategy_common.h", "output/overlay_strategy_single_on_top.cc", "output/overlay_strategy_single_on_top.h", + "output/overlay_strategy_underlay.cc", + "output/overlay_strategy_underlay.h", "output/program_binding.cc", "output/program_binding.h", "output/render_surface_filters.cc", @@ -300,8 +300,12 @@ 'output/overlay_candidate_validator.h', 'output/overlay_processor.cc', 'output/overlay_processor.h', + 'output/overlay_strategy_common.cc', + 'output/overlay_strategy_common.h', 'output/overlay_strategy_single_on_top.cc', 'output/overlay_strategy_single_on_top.h', + 'output/overlay_strategy_underlay.cc', + 'output/overlay_strategy_underlay.h', 'output/program_binding.cc', 'output/program_binding.h', 'output/render_surface_filters.cc', diff --git a/cc/output/overlay_strategy_common.cc b/cc/output/overlay_strategy_common.cc new file mode 100644 index 0000000..b03fbba5 --- /dev/null +++ b/cc/output/overlay_strategy_common.cc @@ -0,0 +1,135 @@ +// Copyright 2015 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/overlay_strategy_common.h" + +#include <limits> + +#include "cc/quads/solid_color_draw_quad.h" +#include "cc/quads/stream_video_draw_quad.h" +#include "cc/quads/texture_draw_quad.h" +#include "ui/gfx/geometry/point3_f.h" +#include "ui/gfx/geometry/rect_conversions.h" +#include "ui/gfx/transform.h" + +namespace cc { + +OverlayStrategyCommon::OverlayStrategyCommon( + OverlayCandidateValidator* capability_checker, + ResourceProvider* resource_provider) + : capability_checker_(capability_checker), + resource_provider_(resource_provider) { +} + +OverlayStrategyCommon::~OverlayStrategyCommon() { +} + +bool OverlayStrategyCommon::IsOverlayQuad(const DrawQuad* draw_quad) { + unsigned int resource_id; + switch (draw_quad->material) { + case DrawQuad::TEXTURE_CONTENT: + resource_id = TextureDrawQuad::MaterialCast(draw_quad)->resource_id; + break; + case DrawQuad::STREAM_VIDEO_CONTENT: + resource_id = StreamVideoDrawQuad::MaterialCast(draw_quad)->resource_id; + break; + default: + return false; + } + return resource_provider_->AllowOverlay(resource_id); +} + +bool OverlayStrategyCommon::IsInvisibleQuad(const DrawQuad* draw_quad) { + if (draw_quad->material == DrawQuad::SOLID_COLOR) { + const SolidColorDrawQuad* solid_quad = + SolidColorDrawQuad::MaterialCast(draw_quad); + SkColor color = solid_quad->color; + float opacity = solid_quad->opacity(); + float alpha = (SkColorGetA(color) * (1.0f / 255.0f)) * opacity; + return solid_quad->ShouldDrawWithBlending() && + alpha < std::numeric_limits<float>::epsilon(); + } + return false; +} + +bool OverlayStrategyCommon::GetTextureQuadInfo(const TextureDrawQuad& quad, + OverlayCandidate* quad_info) { + gfx::OverlayTransform overlay_transform = + OverlayCandidate::GetOverlayTransform(quad.quadTransform(), quad.flipped); + if (quad.background_color != SK_ColorTRANSPARENT || + quad.premultiplied_alpha || + overlay_transform == gfx::OVERLAY_TRANSFORM_INVALID) + return false; + quad_info->resource_id = quad.resource_id; + quad_info->transform = overlay_transform; + quad_info->uv_rect = BoundingRect(quad.uv_top_left, quad.uv_bottom_right); + return true; +} + +bool OverlayStrategyCommon::GetVideoQuadInfo(const StreamVideoDrawQuad& quad, + OverlayCandidate* quad_info) { + gfx::OverlayTransform overlay_transform = + OverlayCandidate::GetOverlayTransform(quad.quadTransform(), false); + if (overlay_transform == gfx::OVERLAY_TRANSFORM_INVALID) + return false; + if (!quad.matrix.IsScaleOrTranslation()) { + // We cannot handle anything other than scaling & translation for texture + // coordinates yet. + return false; + } + quad_info->resource_id = quad.resource_id; + quad_info->transform = overlay_transform; + + gfx::Point3F uv0 = gfx::Point3F(0, 0, 0); + gfx::Point3F uv1 = gfx::Point3F(1, 1, 0); + quad.matrix.TransformPoint(&uv0); + quad.matrix.TransformPoint(&uv1); + gfx::Vector3dF delta = uv1 - uv0; + if (delta.x() < 0) { + quad_info->transform = OverlayCandidate::ModifyTransform( + quad_info->transform, gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL); + float x0 = uv0.x(); + uv0.set_x(uv1.x()); + uv1.set_x(x0); + delta.set_x(-delta.x()); + } + + if (delta.y() < 0) { + // In this situation, uv0y < uv1y. Since we overlay inverted, a request + // to invert the source texture means we can just output the texture + // normally and it will be correct. + quad_info->uv_rect = gfx::RectF(uv0.x(), uv1.y(), delta.x(), -delta.y()); + } else { + quad_info->transform = OverlayCandidate::ModifyTransform( + quad_info->transform, gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL); + quad_info->uv_rect = gfx::RectF(uv0.x(), uv0.y(), delta.x(), delta.y()); + } + return true; +} + +bool OverlayStrategyCommon::GetCandidateQuadInfo(const DrawQuad& draw_quad, + OverlayCandidate* quad_info) { + // All quad checks. + if (draw_quad.needs_blending || draw_quad.shared_quad_state->opacity != 1.f || + draw_quad.shared_quad_state->blend_mode != SkXfermode::kSrcOver_Mode) + return false; + + if (draw_quad.material == DrawQuad::TEXTURE_CONTENT) { + const TextureDrawQuad& quad = *TextureDrawQuad::MaterialCast(&draw_quad); + if (!GetTextureQuadInfo(quad, quad_info)) + return false; + } else if (draw_quad.material == DrawQuad::STREAM_VIDEO_CONTENT) { + const StreamVideoDrawQuad& quad = + *StreamVideoDrawQuad::MaterialCast(&draw_quad); + if (!GetVideoQuadInfo(quad, quad_info)) + return false; + } + + quad_info->format = RGBA_8888; + quad_info->display_rect = OverlayCandidate::GetOverlayRect( + draw_quad.quadTransform(), draw_quad.rect); + return true; +} + +} // namespace cc diff --git a/cc/output/overlay_strategy_common.h b/cc/output/overlay_strategy_common.h new file mode 100644 index 0000000..515a106 --- /dev/null +++ b/cc/output/overlay_strategy_common.h @@ -0,0 +1,49 @@ +// Copyright 2015 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. + +#ifndef CC_OUTPUT_OVERLAY_STRATEGY_COMMON_H_ +#define CC_OUTPUT_OVERLAY_STRATEGY_COMMON_H_ + +#include "cc/base/cc_export.h" +#include "cc/output/overlay_candidate.h" +#include "cc/output/overlay_processor.h" + +namespace cc { +class OverlayCandidateValidator; +class StreamVideoDrawQuad; +class TextureDrawQuad; +class OverlayCandidate; + +class CC_EXPORT OverlayStrategyCommon : public OverlayProcessor::Strategy { + public: + OverlayStrategyCommon(OverlayCandidateValidator* capability_checker, + ResourceProvider* resource_provider); + ~OverlayStrategyCommon() override; + + protected: + bool GetCandidateQuadInfo(const DrawQuad& draw_quad, + OverlayCandidate* quad_info); + + // Returns true if |draw_quad| will not block quads underneath from becoming + // an overlay. + bool IsInvisibleQuad(const DrawQuad* draw_quad); + + // Returns true if |draw_quad| is of a known quad type and contains an + // overlayable resource. + bool IsOverlayQuad(const DrawQuad* draw_quad); + + bool GetTextureQuadInfo(const TextureDrawQuad& quad, + OverlayCandidate* quad_info); + bool GetVideoQuadInfo(const StreamVideoDrawQuad& quad, + OverlayCandidate* quad_info); + + OverlayCandidateValidator* capability_checker_; + ResourceProvider* resource_provider_; + + private: + DISALLOW_COPY_AND_ASSIGN(OverlayStrategyCommon); +}; +} // namespace cc + +#endif // CC_OUTPUT_OVERLAY_STRATEGY_COMMON_H_ diff --git a/cc/output/overlay_strategy_single_on_top.cc b/cc/output/overlay_strategy_single_on_top.cc index 71897ed..65b039e 100644 --- a/cc/output/overlay_strategy_single_on_top.cc +++ b/cc/output/overlay_strategy_single_on_top.cc @@ -7,130 +7,13 @@ #include <limits> #include "cc/quads/draw_quad.h" -#include "cc/quads/solid_color_draw_quad.h" -#include "cc/quads/stream_video_draw_quad.h" -#include "cc/quads/texture_draw_quad.h" -#include "ui/gfx/geometry/point3_f.h" -#include "ui/gfx/geometry/rect_conversions.h" -#include "ui/gfx/transform.h" namespace cc { OverlayStrategySingleOnTop::OverlayStrategySingleOnTop( OverlayCandidateValidator* capability_checker, ResourceProvider* resource_provider) - : capability_checker_(capability_checker), - resource_provider_(resource_provider) {} - -bool OverlayStrategySingleOnTop::IsOverlayQuad(const DrawQuad* draw_quad) { - unsigned int resource_id; - switch (draw_quad->material) { - case DrawQuad::TEXTURE_CONTENT: - resource_id = TextureDrawQuad::MaterialCast(draw_quad)->resource_id; - break; - case DrawQuad::STREAM_VIDEO_CONTENT: - resource_id = StreamVideoDrawQuad::MaterialCast(draw_quad)->resource_id; - break; - default: - return false; - } - return resource_provider_->AllowOverlay(resource_id); -} - -bool OverlayStrategySingleOnTop::GetTextureQuadInfo( - const TextureDrawQuad& quad, - OverlayCandidate* quad_info) { - gfx::OverlayTransform overlay_transform = - OverlayCandidate::GetOverlayTransform(quad.quadTransform(), quad.flipped); - if (quad.background_color != SK_ColorTRANSPARENT || - quad.premultiplied_alpha || - overlay_transform == gfx::OVERLAY_TRANSFORM_INVALID) - return false; - quad_info->resource_id = quad.resource_id; - quad_info->transform = overlay_transform; - quad_info->uv_rect = BoundingRect(quad.uv_top_left, quad.uv_bottom_right); - return true; -} - -bool OverlayStrategySingleOnTop::GetVideoQuadInfo( - const StreamVideoDrawQuad& quad, - OverlayCandidate* quad_info) { - gfx::OverlayTransform overlay_transform = - OverlayCandidate::GetOverlayTransform(quad.quadTransform(), false); - if (overlay_transform == gfx::OVERLAY_TRANSFORM_INVALID) - return false; - if (!quad.matrix.IsScaleOrTranslation()) { - // We cannot handle anything other than scaling & translation for texture - // coordinates yet. - return false; - } - quad_info->resource_id = quad.resource_id; - quad_info->transform = overlay_transform; - - gfx::Point3F uv0 = gfx::Point3F(0, 0, 0); - gfx::Point3F uv1 = gfx::Point3F(1, 1, 0); - quad.matrix.TransformPoint(&uv0); - quad.matrix.TransformPoint(&uv1); - gfx::Vector3dF delta = uv1 - uv0; - if (delta.x() < 0) { - quad_info->transform = OverlayCandidate::ModifyTransform( - quad_info->transform, gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL); - float x0 = uv0.x(); - uv0.set_x(uv1.x()); - uv1.set_x(x0); - delta.set_x(-delta.x()); - } - - if (delta.y() < 0) { - // In this situation, uv0y < uv1y. Since we overlay inverted, a request - // to invert the source texture means we can just output the texture - // normally and it will be correct. - quad_info->uv_rect = gfx::RectF(uv0.x(), uv1.y(), delta.x(), -delta.y()); - } else { - quad_info->transform = OverlayCandidate::ModifyTransform( - quad_info->transform, gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL); - quad_info->uv_rect = gfx::RectF(uv0.x(), uv0.y(), delta.x(), delta.y()); - } - return true; -} - -bool OverlayStrategySingleOnTop::GetCandidateQuadInfo( - const DrawQuad& draw_quad, - OverlayCandidate* quad_info) { - // All quad checks. - if (draw_quad.needs_blending || draw_quad.shared_quad_state->opacity != 1.f || - draw_quad.shared_quad_state->blend_mode != SkXfermode::kSrcOver_Mode) - return false; - - if (draw_quad.material == DrawQuad::TEXTURE_CONTENT) { - const TextureDrawQuad& quad = *TextureDrawQuad::MaterialCast(&draw_quad); - if (!GetTextureQuadInfo(quad, quad_info)) - return false; - } else if (draw_quad.material == DrawQuad::STREAM_VIDEO_CONTENT) { - const StreamVideoDrawQuad& quad = - *StreamVideoDrawQuad::MaterialCast(&draw_quad); - if (!GetVideoQuadInfo(quad, quad_info)) - return false; - } - - quad_info->format = RGBA_8888; - quad_info->display_rect = OverlayCandidate::GetOverlayRect( - draw_quad.quadTransform(), draw_quad.rect); - return true; -} - -bool OverlayStrategySingleOnTop::IsInvisibleQuad(const DrawQuad* draw_quad) { - if (draw_quad->material == DrawQuad::SOLID_COLOR) { - const SolidColorDrawQuad* solid_quad = - SolidColorDrawQuad::MaterialCast(draw_quad); - SkColor color = solid_quad->color; - float opacity = solid_quad->opacity(); - float alpha = (SkColorGetA(color) * (1.0f / 255.0f)) * opacity; - // Ignore transparent solid color quads. - return solid_quad->ShouldDrawWithBlending() && - alpha < std::numeric_limits<float>::epsilon(); - } - return false; + : OverlayStrategyCommon(capability_checker, resource_provider) { } bool OverlayStrategySingleOnTop::Attempt( diff --git a/cc/output/overlay_strategy_single_on_top.h b/cc/output/overlay_strategy_single_on_top.h index a3fec0a..eeecd32 100644 --- a/cc/output/overlay_strategy_single_on_top.h +++ b/cc/output/overlay_strategy_single_on_top.h @@ -10,14 +10,14 @@ #include "cc/base/cc_export.h" #include "cc/output/overlay_candidate.h" #include "cc/output/overlay_processor.h" +#include "cc/output/overlay_strategy_common.h" #include "cc/quads/render_pass.h" namespace cc { -class OverlayCandidateValidator; class StreamVideoDrawQuad; class TextureDrawQuad; -class CC_EXPORT OverlayStrategySingleOnTop : public OverlayProcessor::Strategy { +class CC_EXPORT OverlayStrategySingleOnTop : public OverlayStrategyCommon { public: OverlayStrategySingleOnTop(OverlayCandidateValidator* capability_checker, ResourceProvider* resource_provider); @@ -25,21 +25,6 @@ class CC_EXPORT OverlayStrategySingleOnTop : public OverlayProcessor::Strategy { OverlayCandidateList* candidate_list) override; private: - bool IsOverlayQuad(const DrawQuad* draw_quad); - bool GetCandidateQuadInfo(const DrawQuad& draw_quad, - OverlayCandidate* quad_info); - - // Returns true if |draw_quad| will not block quads underneath from becoming - // an overlay. - bool IsInvisibleQuad(const DrawQuad* draw_quad); - - bool GetTextureQuadInfo(const TextureDrawQuad& quad, - OverlayCandidate* quad_info); - bool GetVideoQuadInfo(const StreamVideoDrawQuad& quad, - OverlayCandidate* quad_info); - - OverlayCandidateValidator* capability_checker_; - ResourceProvider* resource_provider_; DISALLOW_COPY_AND_ASSIGN(OverlayStrategySingleOnTop); }; diff --git a/cc/output/overlay_strategy_underlay.cc b/cc/output/overlay_strategy_underlay.cc new file mode 100644 index 0000000..631ce03 --- /dev/null +++ b/cc/output/overlay_strategy_underlay.cc @@ -0,0 +1,69 @@ +// Copyright 2014 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/overlay_strategy_underlay.h" + +#include "cc/quads/draw_quad.h" +#include "cc/quads/solid_color_draw_quad.h" + +namespace cc { + +OverlayStrategyUnderlay::OverlayStrategyUnderlay( + OverlayCandidateValidator* capability_checker, + ResourceProvider* resource_provider) + : OverlayStrategyCommon(capability_checker, resource_provider) { +} + +bool OverlayStrategyUnderlay::Attempt( + RenderPassList* render_passes_in_draw_order, + OverlayCandidateList* candidate_list) { + if (!capability_checker_) + return false; + + RenderPass* root_render_pass = render_passes_in_draw_order->back(); + DCHECK(root_render_pass); + + OverlayCandidate candidate; + QuadList& quad_list = root_render_pass->quad_list; + auto candidate_iterator = quad_list.end(); + for (auto it = quad_list.begin(); it != quad_list.end(); ++it) { + if (IsOverlayQuad(*it) && GetCandidateQuadInfo(**it, &candidate)) { + candidate_iterator = it; + break; + } + } + if (candidate_iterator == quad_list.end()) + return false; + + // Add our primary surface. + OverlayCandidateList candidates; + OverlayCandidate main_image; + main_image.display_rect = root_render_pass->output_rect; + candidates.push_back(main_image); + + // Add the overlay. + candidate.plane_z_order = -1; + candidates.push_back(candidate); + + // Check for support. + capability_checker_->CheckOverlaySupport(&candidates); + + // If the candidate can be handled by an overlay, create a pass for it. We + // need to switch out the video quad with a black transparent one. + if (candidates[1].overlay_handled) { + const SharedQuadState* shared_quad_state = + candidate_iterator->shared_quad_state; + gfx::Rect rect = candidate_iterator->visible_rect; + SolidColorDrawQuad* replacement = + quad_list.ReplaceExistingElement<SolidColorDrawQuad>( + candidate_iterator); + replacement->SetAll(shared_quad_state, rect, rect, rect, false, + SK_ColorTRANSPARENT, true); + candidate_list->swap(candidates); + return true; + } + return false; +} + +} // namespace cc diff --git a/cc/output/overlay_strategy_underlay.h b/cc/output/overlay_strategy_underlay.h new file mode 100644 index 0000000..881e170 --- /dev/null +++ b/cc/output/overlay_strategy_underlay.h @@ -0,0 +1,32 @@ +// Copyright 2014 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. + +#ifndef CC_OUTPUT_OVERLAY_STRATEGY_UNDERLAY_H_ +#define CC_OUTPUT_OVERLAY_STRATEGY_UNDERLAY_H_ + +#include "cc/output/overlay_strategy_common.h" + +namespace cc { +class StreamVideoDrawQuad; +class TextureDrawQuad; + +// The underlay strategy looks for a video quad without regard to quads above +// it. The video is "underlaid" through a black transparent quad substituted +// for the video quad. The overlay content can then be blended in by the +// hardware under the the scene. This is only valid for overlay contents that +// are fully opaque. +class CC_EXPORT OverlayStrategyUnderlay : public OverlayStrategyCommon { + public: + OverlayStrategyUnderlay(OverlayCandidateValidator* capability_checker, + ResourceProvider* resource_provider); + bool Attempt(RenderPassList* render_passes_in_draw_order, + OverlayCandidateList* candidate_list) override; + + private: + DISALLOW_COPY_AND_ASSIGN(OverlayStrategyUnderlay); +}; + +} // namespace cc + +#endif // CC_OUTPUT_OVERLAY_STRATEGY_UNDERLAY_H_ diff --git a/cc/output/overlay_unittest.cc b/cc/output/overlay_unittest.cc index 75fbb6e..9849286 100644 --- a/cc/output/overlay_unittest.cc +++ b/cc/output/overlay_unittest.cc @@ -10,6 +10,7 @@ #include "cc/output/overlay_candidate_validator.h" #include "cc/output/overlay_processor.h" #include "cc/output/overlay_strategy_single_on_top.h" +#include "cc/output/overlay_strategy_underlay.h" #include "cc/quads/checkerboard_draw_quad.h" #include "cc/quads/render_pass.h" #include "cc/quads/stream_video_draw_quad.h" @@ -69,30 +70,26 @@ void SingleOverlayValidator::CheckOverlaySupport( candidate.overlay_handled = true; } +template <typename OverlayStrategyType> class SingleOverlayProcessor : public OverlayProcessor { public: SingleOverlayProcessor(OutputSurface* surface, - ResourceProvider* resource_provider); + ResourceProvider* resource_provider) + : OverlayProcessor(surface, resource_provider) { + EXPECT_EQ(surface, surface_); + EXPECT_EQ(resource_provider, resource_provider_); + } + // Virtual to allow testing different strategies. - void Initialize() override; + void Initialize() override { + OverlayCandidateValidator* candidates = + surface_->overlay_candidate_validator(); + ASSERT_TRUE(candidates != NULL); + strategies_.push_back(scoped_ptr<Strategy>( + new OverlayStrategyType(candidates, resource_provider_))); + } }; -SingleOverlayProcessor::SingleOverlayProcessor( - OutputSurface* surface, - ResourceProvider* resource_provider) - : OverlayProcessor(surface, resource_provider) { - EXPECT_EQ(surface, surface_); - EXPECT_EQ(resource_provider, resource_provider_); -} - -void SingleOverlayProcessor::Initialize() { - OverlayCandidateValidator* candidates = - surface_->overlay_candidate_validator(); - ASSERT_TRUE(candidates != NULL); - strategies_.push_back(scoped_ptr<Strategy>( - new OverlayStrategySingleOnTop(candidates, resource_provider_))); -} - class DefaultOverlayProcessor : public OverlayProcessor { public: DefaultOverlayProcessor(OutputSurface* surface, @@ -303,7 +300,8 @@ TEST(OverlayTest, OverlaysProcessorHasStrategy) { EXPECT_GE(1U, overlay_processor->GetStrategyCount()); } -class SingleOverlayOnTopTest : public testing::Test { +template <typename OverlayStrategyType> +class OverlayTest : public testing::Test { protected: void SetUp() override { provider_ = TestContextProvider::Create(); @@ -321,7 +319,7 @@ class SingleOverlayOnTopTest : public testing::Test { false, 1); - overlay_processor_.reset(new SingleOverlayProcessor( + overlay_processor_.reset(new SingleOverlayProcessor<OverlayStrategyType>( output_surface_.get(), resource_provider_.get())); overlay_processor_->Initialize(); } @@ -331,9 +329,12 @@ class SingleOverlayOnTopTest : public testing::Test { FakeOutputSurfaceClient client_; scoped_ptr<SharedBitmapManager> shared_bitmap_manager_; scoped_ptr<ResourceProvider> resource_provider_; - scoped_ptr<SingleOverlayProcessor> overlay_processor_; + scoped_ptr<SingleOverlayProcessor<OverlayStrategyType>> overlay_processor_; }; +typedef OverlayTest<OverlayStrategySingleOnTop> SingleOverlayOnTopTest; +typedef OverlayTest<OverlayStrategyUnderlay> UnderlayTest; + TEST_F(SingleOverlayOnTopTest, SuccessfullOverlay) { scoped_ptr<RenderPass> pass = CreateRenderPass(); TextureDrawQuad* original_quad = @@ -762,6 +763,52 @@ TEST_F(SingleOverlayOnTopTest, AllowVideoYMirrorTransform) { EXPECT_EQ(2U, candidate_list.size()); } +TEST_F(UnderlayTest, OverlayLayerUnderMainLayer) { + scoped_ptr<RenderPass> pass = CreateRenderPass(); + CreateFullscreenCheckeredQuad(resource_provider_.get(), + pass->shared_quad_state_list.back(), + pass.get()); + CreateCandidateQuadAt(resource_provider_.get(), + pass->shared_quad_state_list.back(), pass.get(), + kOverlayBottomRightRect); + + RenderPassList pass_list; + pass_list.push_back(pass.Pass()); + + OverlayCandidateList candidate_list; + overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); + EXPECT_EQ(1U, pass_list.size()); + ASSERT_EQ(2U, candidate_list.size()); + EXPECT_EQ(0, candidate_list[0].plane_z_order); + EXPECT_EQ(-1, candidate_list[1].plane_z_order); + EXPECT_EQ(2U, pass_list[0]->quad_list.size()); + // The overlay quad should have changed to a SOLID_COLOR quad. + EXPECT_EQ(pass_list[0]->quad_list.back()->material, DrawQuad::SOLID_COLOR); +} + +TEST_F(UnderlayTest, AllowOnTop) { + scoped_ptr<RenderPass> pass = CreateRenderPass(); + CreateFullscreenCandidateQuad(resource_provider_.get(), + pass->shared_quad_state_list.back(), + pass.get()); + pass->CreateAndAppendSharedQuadState()->opacity = 0.5f; + CreateFullscreenCheckeredQuad(resource_provider_.get(), + pass->shared_quad_state_list.back(), + pass.get()); + + RenderPassList pass_list; + pass_list.push_back(pass.Pass()); + + OverlayCandidateList candidate_list; + overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); + EXPECT_EQ(1U, pass_list.size()); + ASSERT_EQ(2U, candidate_list.size()); + EXPECT_EQ(0, candidate_list[0].plane_z_order); + EXPECT_EQ(-1, candidate_list[1].plane_z_order); + // The overlay quad should have changed to a SOLID_COLOR quad. + EXPECT_EQ(pass_list[0]->quad_list.front()->material, DrawQuad::SOLID_COLOR); +} + class OverlayInfoRendererGL : public GLRenderer { public: OverlayInfoRendererGL(RendererClient* client, diff --git a/cc/quads/list_container.h b/cc/quads/list_container.h index 7abbe27..38a34b8 100644 --- a/cc/quads/list_container.h +++ b/cc/quads/list_container.h @@ -209,6 +209,12 @@ class CC_EXPORT ListContainer { return new (Allocate(sizeof(DerivedElementType))) DerivedElementType(*source); } + // Construct a new element on top of an existing one. + template <typename DerivedElementType> + DerivedElementType* ReplaceExistingElement(Iterator at) { + at->~BaseElementType(); + return new (*at) DerivedElementType(); + } size_t size() const; bool empty() const; diff --git a/cc/quads/list_container_unittest.cc b/cc/quads/list_container_unittest.cc index de88750..68e6061 100644 --- a/cc/quads/list_container_unittest.cc +++ b/cc/quads/list_container_unittest.cc @@ -54,16 +54,22 @@ class SimpleDrawQuadConstructMagicNumberTwo : public SimpleDrawQuad { } }; -class MockDrawQuad : public DrawQuad { +class MockDrawQuad : public SimpleDrawQuadConstructMagicNumberOne { public: ~MockDrawQuad() override { Destruct(); } - void IterateResources(const ResourceIteratorCallback& callback) override {} - void ExtendValue(base::trace_event::TracedValue* value) const override {} MOCK_METHOD0(Destruct, void()); }; +class MockDrawQuadSubclass : public MockDrawQuad { + public: + MockDrawQuadSubclass() { set_value(kMagicNumberToUseForDrawQuadTwo); } +}; + +const size_t kLargestQuadSize = + std::max(LargestDrawQuadSize(), sizeof(MockDrawQuadSubclass)); + TEST(ListContainerTest, ConstructorCalledInAllocateAndConstruct) { - ListContainer<DrawQuad> list(LargestDrawQuadSize()); + ListContainer<DrawQuad> list(kLargestQuadSize); size_t size = 2; SimpleDrawQuadConstructMagicNumberOne* dq_1 = @@ -80,7 +86,7 @@ TEST(ListContainerTest, ConstructorCalledInAllocateAndConstruct) { } TEST(ListContainerTest, DestructorCalled) { - ListContainer<DrawQuad> list(LargestDrawQuadSize()); + ListContainer<DrawQuad> list(kLargestQuadSize); size_t size = 1; MockDrawQuad* dq_1 = list.AllocateAndConstruct<MockDrawQuad>(); @@ -91,7 +97,7 @@ TEST(ListContainerTest, DestructorCalled) { } TEST(ListContainerTest, DestructorCalledOnceWhenClear) { - ListContainer<DrawQuad> list(LargestDrawQuadSize()); + ListContainer<DrawQuad> list(kLargestQuadSize); size_t size = 1; MockDrawQuad* dq_1 = list.AllocateAndConstruct<MockDrawQuad>(); @@ -112,8 +118,34 @@ TEST(ListContainerTest, DestructorCalledOnceWhenClear) { separator.Call(); } +TEST(ListContainerTest, ReplaceExistingElement) { + ListContainer<DrawQuad> list(kLargestQuadSize); + size_t size = 1; + MockDrawQuad* dq_1 = list.AllocateAndConstruct<MockDrawQuad>(); + + EXPECT_EQ(size, list.size()); + EXPECT_EQ(dq_1, list.front()); + + // Make sure destructor is called once during clear, and won't be called + // again. + testing::MockFunction<void()> separator; + { + testing::InSequence s; + EXPECT_CALL(*dq_1, Destruct()); + EXPECT_CALL(separator, Call()); + EXPECT_CALL(*dq_1, Destruct()).Times(0); + } + + list.ReplaceExistingElement<MockDrawQuadSubclass>(list.begin()); + EXPECT_EQ(kMagicNumberToUseForDrawQuadTwo, dq_1->get_value()); + separator.Call(); + + EXPECT_CALL(*dq_1, Destruct()); + list.clear(); +} + TEST(ListContainerTest, DestructorCalledOnceWhenErase) { - ListContainer<DrawQuad> list(LargestDrawQuadSize()); + ListContainer<DrawQuad> list(kLargestQuadSize); size_t size = 1; MockDrawQuad* dq_1 = list.AllocateAndConstruct<MockDrawQuad>(); @@ -434,7 +466,7 @@ TEST(ListContainerTest, SimpleReverseInsertionSharedQuadState) { } TEST(ListContainerTest, SimpleDeletion) { - ListContainer<DrawQuad> list(LargestDrawQuadSize()); + ListContainer<DrawQuad> list(kLargestQuadSize); std::vector<SimpleDrawQuad*> sdq_list; size_t size = 10; for (size_t i = 0; i < size; ++i) { @@ -456,7 +488,7 @@ TEST(ListContainerTest, SimpleDeletion) { } TEST(ListContainerTest, SimpleIterationAndManipulation) { - ListContainer<DrawQuad> list(LargestDrawQuadSize()); + ListContainer<DrawQuad> list(kLargestQuadSize); std::vector<SimpleDrawQuad*> sdq_list; size_t size = 10; for (size_t i = 0; i < size; ++i) { @@ -481,7 +513,7 @@ TEST(ListContainerTest, SimpleIterationAndManipulation) { } TEST(ListContainerTest, SimpleManipulationWithIndexSimpleDrawQuad) { - ListContainer<DrawQuad> list(LargestDrawQuadSize()); + ListContainer<DrawQuad> list(kLargestQuadSize); std::vector<SimpleDrawQuad*> dq_list; size_t size = 10; for (size_t i = 0; i < size; ++i) { |