Use multiline attribute to check for IA2_STATE_MULTILINE.
[chromium-blink-merge.git] / cc / output / overlay_unittest.cc
blob98492869d0764cdba3263096a19d2e300c4e06f5
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/base/scoped_ptr_vector.h"
6 #include "cc/output/compositor_frame_metadata.h"
7 #include "cc/output/gl_renderer.h"
8 #include "cc/output/output_surface.h"
9 #include "cc/output/output_surface_client.h"
10 #include "cc/output/overlay_candidate_validator.h"
11 #include "cc/output/overlay_processor.h"
12 #include "cc/output/overlay_strategy_single_on_top.h"
13 #include "cc/output/overlay_strategy_underlay.h"
14 #include "cc/quads/checkerboard_draw_quad.h"
15 #include "cc/quads/render_pass.h"
16 #include "cc/quads/stream_video_draw_quad.h"
17 #include "cc/quads/texture_draw_quad.h"
18 #include "cc/resources/resource_provider.h"
19 #include "cc/resources/texture_mailbox.h"
20 #include "cc/test/fake_output_surface_client.h"
21 #include "cc/test/geometry_test_utils.h"
22 #include "cc/test/test_context_provider.h"
23 #include "cc/test/test_shared_bitmap_manager.h"
24 #include "testing/gmock/include/gmock/gmock.h"
25 #include "testing/gtest/include/gtest/gtest.h"
27 using testing::_;
28 using testing::Mock;
30 namespace cc {
31 namespace {
33 const gfx::Rect kOverlayRect(0, 0, 128, 128);
34 const gfx::Rect kOverlayTopLeftRect(0, 0, 64, 64);
35 const gfx::Rect kOverlayBottomRightRect(64, 64, 64, 64);
36 const gfx::PointF kUVTopLeft(0.1f, 0.2f);
37 const gfx::PointF kUVBottomRight(1.0f, 1.0f);
38 const gfx::Transform kNormalTransform =
39 gfx::Transform(0.9f, 0, 0, 0.8f, 0.1f, 0.2f); // x,y -> x,y.
40 const gfx::Transform kXMirrorTransform =
41 gfx::Transform(-0.9f, 0, 0, 0.8f, 1.0f, 0.2f); // x,y -> 1-x,y.
42 const gfx::Transform kYMirrorTransform =
43 gfx::Transform(0.9f, 0, 0, -0.8f, 0.1f, 1.0f); // x,y -> x,1-y.
44 const gfx::Transform kBothMirrorTransform =
45 gfx::Transform(-0.9f, 0, 0, -0.8f, 1.0f, 1.0f); // x,y -> 1-x,1-y.
46 const gfx::Transform kSwapTransform =
47 gfx::Transform(0, 1, 1, 0, 0, 0); // x,y -> y,x.
49 void MailboxReleased(unsigned sync_point,
50 bool lost_resource,
51 BlockingTaskRunner* main_thread_task_runner) {
54 class SingleOverlayValidator : public OverlayCandidateValidator {
55 public:
56 void CheckOverlaySupport(OverlayCandidateList* surfaces) override;
59 void SingleOverlayValidator::CheckOverlaySupport(
60 OverlayCandidateList* surfaces) {
61 ASSERT_EQ(2U, surfaces->size());
63 OverlayCandidate& candidate = surfaces->back();
64 if (candidate.display_rect.width() == 64)
65 EXPECT_EQ(kOverlayBottomRightRect, candidate.display_rect);
66 else
67 EXPECT_EQ(kOverlayRect, candidate.display_rect);
68 EXPECT_EQ(BoundingRect(kUVTopLeft, kUVBottomRight).ToString(),
69 candidate.uv_rect.ToString());
70 candidate.overlay_handled = true;
73 template <typename OverlayStrategyType>
74 class SingleOverlayProcessor : public OverlayProcessor {
75 public:
76 SingleOverlayProcessor(OutputSurface* surface,
77 ResourceProvider* resource_provider)
78 : OverlayProcessor(surface, resource_provider) {
79 EXPECT_EQ(surface, surface_);
80 EXPECT_EQ(resource_provider, resource_provider_);
83 // Virtual to allow testing different strategies.
84 void Initialize() override {
85 OverlayCandidateValidator* candidates =
86 surface_->overlay_candidate_validator();
87 ASSERT_TRUE(candidates != NULL);
88 strategies_.push_back(scoped_ptr<Strategy>(
89 new OverlayStrategyType(candidates, resource_provider_)));
93 class DefaultOverlayProcessor : public OverlayProcessor {
94 public:
95 DefaultOverlayProcessor(OutputSurface* surface,
96 ResourceProvider* resource_provider);
97 size_t GetStrategyCount();
100 DefaultOverlayProcessor::DefaultOverlayProcessor(
101 OutputSurface* surface,
102 ResourceProvider* resource_provider)
103 : OverlayProcessor(surface, resource_provider) {}
105 size_t DefaultOverlayProcessor::GetStrategyCount() {
106 return strategies_.size();
109 class OverlayOutputSurface : public OutputSurface {
110 public:
111 explicit OverlayOutputSurface(scoped_refptr<ContextProvider> context_provider)
112 : OutputSurface(context_provider) {}
114 // OutputSurface implementation
115 void SwapBuffers(CompositorFrame* frame) override;
117 void InitWithSingleOverlayValidator() {
118 overlay_candidate_validator_.reset(new SingleOverlayValidator);
122 void OverlayOutputSurface::SwapBuffers(CompositorFrame* frame) {
123 client_->DidSwapBuffers();
124 client_->DidSwapBuffersComplete();
127 scoped_ptr<RenderPass> CreateRenderPass() {
128 RenderPassId id(1, 0);
129 gfx::Rect output_rect(0, 0, 256, 256);
130 bool has_transparent_background = true;
132 scoped_ptr<RenderPass> pass = RenderPass::Create();
133 pass->SetAll(id,
134 output_rect,
135 output_rect,
136 gfx::Transform(),
137 has_transparent_background);
139 SharedQuadState* shared_state = pass->CreateAndAppendSharedQuadState();
140 shared_state->opacity = 1.f;
141 return pass.Pass();
144 ResourceProvider::ResourceId CreateResource(
145 ResourceProvider* resource_provider) {
146 unsigned sync_point = 0;
147 TextureMailbox mailbox =
148 TextureMailbox(gpu::Mailbox::Generate(), GL_TEXTURE_2D, sync_point);
149 mailbox.set_allow_overlay(true);
150 scoped_ptr<SingleReleaseCallbackImpl> release_callback =
151 SingleReleaseCallbackImpl::Create(base::Bind(&MailboxReleased));
153 return resource_provider->CreateResourceFromTextureMailbox(
154 mailbox, release_callback.Pass());
157 SolidColorDrawQuad* CreateSolidColorQuadAt(
158 const SharedQuadState* shared_quad_state,
159 SkColor color,
160 RenderPass* render_pass,
161 const gfx::Rect& rect) {
162 SolidColorDrawQuad* quad =
163 render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
164 quad->SetNew(shared_quad_state, rect, rect, color, false);
165 return quad;
168 TextureDrawQuad* CreateCandidateQuadAt(ResourceProvider* resource_provider,
169 const SharedQuadState* shared_quad_state,
170 RenderPass* render_pass,
171 const gfx::Rect& rect) {
172 ResourceProvider::ResourceId resource_id = CreateResource(resource_provider);
173 bool premultiplied_alpha = false;
174 bool flipped = false;
175 bool nearest_neighbor = false;
176 float vertex_opacity[4] = {1.0f, 1.0f, 1.0f, 1.0f};
178 TextureDrawQuad* overlay_quad =
179 render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
180 overlay_quad->SetNew(shared_quad_state,
181 rect,
182 rect,
183 rect,
184 resource_id,
185 premultiplied_alpha,
186 kUVTopLeft,
187 kUVBottomRight,
188 SK_ColorTRANSPARENT,
189 vertex_opacity,
190 flipped,
191 nearest_neighbor);
193 return overlay_quad;
196 StreamVideoDrawQuad* CreateCandidateVideoQuadAt(
197 ResourceProvider* resource_provider,
198 const SharedQuadState* shared_quad_state,
199 RenderPass* render_pass,
200 const gfx::Rect& rect,
201 const gfx::Transform& transform) {
202 ResourceProvider::ResourceId resource_id = CreateResource(resource_provider);
204 StreamVideoDrawQuad* overlay_quad =
205 render_pass->CreateAndAppendDrawQuad<StreamVideoDrawQuad>();
206 overlay_quad->SetNew(shared_quad_state, rect, rect, rect, resource_id,
207 transform);
209 return overlay_quad;
212 TextureDrawQuad* CreateFullscreenCandidateQuad(
213 ResourceProvider* resource_provider,
214 const SharedQuadState* shared_quad_state,
215 RenderPass* render_pass) {
216 return CreateCandidateQuadAt(
217 resource_provider, shared_quad_state, render_pass, kOverlayRect);
220 StreamVideoDrawQuad* CreateFullscreenCandidateVideoQuad(
221 ResourceProvider* resource_provider,
222 const SharedQuadState* shared_quad_state,
223 RenderPass* render_pass,
224 const gfx::Transform& transform) {
225 return CreateCandidateVideoQuadAt(resource_provider, shared_quad_state,
226 render_pass, kOverlayRect, transform);
229 void CreateCheckeredQuadAt(ResourceProvider* resource_provider,
230 const SharedQuadState* shared_quad_state,
231 RenderPass* render_pass,
232 const gfx::Rect& rect) {
233 CheckerboardDrawQuad* checkerboard_quad =
234 render_pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
235 checkerboard_quad->SetNew(shared_quad_state, rect, rect, SkColor(), 1.f);
238 void CreateFullscreenCheckeredQuad(ResourceProvider* resource_provider,
239 const SharedQuadState* shared_quad_state,
240 RenderPass* render_pass) {
241 CreateCheckeredQuadAt(
242 resource_provider, shared_quad_state, render_pass, kOverlayRect);
245 static void CompareRenderPassLists(const RenderPassList& expected_list,
246 const RenderPassList& actual_list) {
247 EXPECT_EQ(expected_list.size(), actual_list.size());
248 for (size_t i = 0; i < actual_list.size(); ++i) {
249 RenderPass* expected = expected_list[i];
250 RenderPass* actual = actual_list[i];
252 EXPECT_EQ(expected->id, actual->id);
253 EXPECT_EQ(expected->output_rect, actual->output_rect);
254 EXPECT_EQ(expected->transform_to_root_target,
255 actual->transform_to_root_target);
256 EXPECT_EQ(expected->damage_rect, actual->damage_rect);
257 EXPECT_EQ(expected->has_transparent_background,
258 actual->has_transparent_background);
260 EXPECT_EQ(expected->shared_quad_state_list.size(),
261 actual->shared_quad_state_list.size());
262 EXPECT_EQ(expected->quad_list.size(), actual->quad_list.size());
264 for (auto exp_iter = expected->quad_list.cbegin(),
265 act_iter = actual->quad_list.cbegin();
266 exp_iter != expected->quad_list.cend();
267 ++exp_iter, ++act_iter) {
268 EXPECT_EQ(exp_iter->rect.ToString(), act_iter->rect.ToString());
269 EXPECT_EQ(exp_iter->shared_quad_state->content_bounds.ToString(),
270 act_iter->shared_quad_state->content_bounds.ToString());
275 TEST(OverlayTest, NoOverlaysByDefault) {
276 scoped_refptr<TestContextProvider> provider = TestContextProvider::Create();
277 OverlayOutputSurface output_surface(provider);
278 EXPECT_EQ(NULL, output_surface.overlay_candidate_validator());
280 output_surface.InitWithSingleOverlayValidator();
281 EXPECT_TRUE(output_surface.overlay_candidate_validator() != NULL);
284 TEST(OverlayTest, OverlaysProcessorHasStrategy) {
285 scoped_refptr<TestContextProvider> provider = TestContextProvider::Create();
286 OverlayOutputSurface output_surface(provider);
287 FakeOutputSurfaceClient client;
288 EXPECT_TRUE(output_surface.BindToClient(&client));
289 output_surface.InitWithSingleOverlayValidator();
290 EXPECT_TRUE(output_surface.overlay_candidate_validator() != NULL);
292 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
293 new TestSharedBitmapManager());
294 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
295 &output_surface, shared_bitmap_manager.get(), NULL, NULL, 0, false, 1));
297 scoped_ptr<DefaultOverlayProcessor> overlay_processor(
298 new DefaultOverlayProcessor(&output_surface, resource_provider.get()));
299 overlay_processor->Initialize();
300 EXPECT_GE(1U, overlay_processor->GetStrategyCount());
303 template <typename OverlayStrategyType>
304 class OverlayTest : public testing::Test {
305 protected:
306 void SetUp() override {
307 provider_ = TestContextProvider::Create();
308 output_surface_.reset(new OverlayOutputSurface(provider_));
309 EXPECT_TRUE(output_surface_->BindToClient(&client_));
310 output_surface_->InitWithSingleOverlayValidator();
311 EXPECT_TRUE(output_surface_->overlay_candidate_validator() != NULL);
313 shared_bitmap_manager_.reset(new TestSharedBitmapManager());
314 resource_provider_ = ResourceProvider::Create(output_surface_.get(),
315 shared_bitmap_manager_.get(),
316 NULL,
317 NULL,
319 false,
322 overlay_processor_.reset(new SingleOverlayProcessor<OverlayStrategyType>(
323 output_surface_.get(), resource_provider_.get()));
324 overlay_processor_->Initialize();
327 scoped_refptr<TestContextProvider> provider_;
328 scoped_ptr<OverlayOutputSurface> output_surface_;
329 FakeOutputSurfaceClient client_;
330 scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
331 scoped_ptr<ResourceProvider> resource_provider_;
332 scoped_ptr<SingleOverlayProcessor<OverlayStrategyType>> overlay_processor_;
335 typedef OverlayTest<OverlayStrategySingleOnTop> SingleOverlayOnTopTest;
336 typedef OverlayTest<OverlayStrategyUnderlay> UnderlayTest;
338 TEST_F(SingleOverlayOnTopTest, SuccessfullOverlay) {
339 scoped_ptr<RenderPass> pass = CreateRenderPass();
340 TextureDrawQuad* original_quad =
341 CreateFullscreenCandidateQuad(resource_provider_.get(),
342 pass->shared_quad_state_list.back(),
343 pass.get());
344 unsigned original_resource_id = original_quad->resource_id;
346 // Add something behind it.
347 CreateFullscreenCheckeredQuad(resource_provider_.get(),
348 pass->shared_quad_state_list.back(),
349 pass.get());
350 CreateFullscreenCheckeredQuad(resource_provider_.get(),
351 pass->shared_quad_state_list.back(),
352 pass.get());
354 RenderPassList pass_list;
355 pass_list.push_back(pass.Pass());
357 // Check for potential candidates.
358 OverlayCandidateList candidate_list;
359 overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
361 ASSERT_EQ(1U, pass_list.size());
362 ASSERT_EQ(2U, candidate_list.size());
364 RenderPass* main_pass = pass_list.back();
365 // Check that the quad is gone.
366 EXPECT_EQ(2U, main_pass->quad_list.size());
367 const QuadList& quad_list = main_pass->quad_list;
368 for (QuadList::ConstBackToFrontIterator it = quad_list.BackToFrontBegin();
369 it != quad_list.BackToFrontEnd();
370 ++it) {
371 EXPECT_NE(DrawQuad::TEXTURE_CONTENT, it->material);
374 // Check that the right resource id got extracted.
375 EXPECT_EQ(original_resource_id, candidate_list.back().resource_id);
378 TEST_F(SingleOverlayOnTopTest, NoCandidates) {
379 scoped_ptr<RenderPass> pass = CreateRenderPass();
380 CreateFullscreenCheckeredQuad(resource_provider_.get(),
381 pass->shared_quad_state_list.back(),
382 pass.get());
383 CreateFullscreenCheckeredQuad(resource_provider_.get(),
384 pass->shared_quad_state_list.back(),
385 pass.get());
387 RenderPassList pass_list;
388 pass_list.push_back(pass.Pass());
390 RenderPassList original_pass_list;
391 RenderPass::CopyAll(pass_list, &original_pass_list);
393 OverlayCandidateList candidate_list;
394 overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
395 EXPECT_EQ(0U, candidate_list.size());
396 // There should be nothing new here.
397 CompareRenderPassLists(pass_list, original_pass_list);
400 TEST_F(SingleOverlayOnTopTest, OccludedCandidates) {
401 scoped_ptr<RenderPass> pass = CreateRenderPass();
402 CreateFullscreenCheckeredQuad(resource_provider_.get(),
403 pass->shared_quad_state_list.back(),
404 pass.get());
405 CreateFullscreenCheckeredQuad(resource_provider_.get(),
406 pass->shared_quad_state_list.back(),
407 pass.get());
409 CreateFullscreenCandidateQuad(resource_provider_.get(),
410 pass->shared_quad_state_list.back(),
411 pass.get());
413 RenderPassList pass_list;
414 pass_list.push_back(pass.Pass());
416 RenderPassList original_pass_list;
417 RenderPass::CopyAll(pass_list, &original_pass_list);
419 OverlayCandidateList candidate_list;
420 overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
421 EXPECT_EQ(0U, candidate_list.size());
422 // There should be nothing new here.
423 CompareRenderPassLists(pass_list, original_pass_list);
426 // Test with multiple render passes.
427 TEST_F(SingleOverlayOnTopTest, MultipleRenderPasses) {
428 RenderPassList pass_list;
429 pass_list.push_back(CreateRenderPass());
431 scoped_ptr<RenderPass> pass = CreateRenderPass();
432 CreateFullscreenCandidateQuad(resource_provider_.get(),
433 pass->shared_quad_state_list.back(),
434 pass.get());
436 // Add something behind it.
437 CreateFullscreenCheckeredQuad(resource_provider_.get(),
438 pass->shared_quad_state_list.back(),
439 pass.get());
440 CreateFullscreenCheckeredQuad(resource_provider_.get(),
441 pass->shared_quad_state_list.back(),
442 pass.get());
444 pass_list.push_back(pass.Pass());
446 RenderPassList original_pass_list;
447 RenderPass::CopyAll(pass_list, &original_pass_list);
449 // Check for potential candidates.
450 OverlayCandidateList candidate_list;
451 overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
452 EXPECT_EQ(2U, candidate_list.size());
454 // This should be the same.
455 ASSERT_EQ(2U, pass_list.size());
458 TEST_F(SingleOverlayOnTopTest, RejectPremultipliedAlpha) {
459 scoped_ptr<RenderPass> pass = CreateRenderPass();
460 TextureDrawQuad* quad =
461 CreateFullscreenCandidateQuad(resource_provider_.get(),
462 pass->shared_quad_state_list.back(),
463 pass.get());
464 quad->premultiplied_alpha = true;
466 RenderPassList pass_list;
467 pass_list.push_back(pass.Pass());
468 OverlayCandidateList candidate_list;
469 overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
470 EXPECT_EQ(1U, pass_list.size());
471 EXPECT_EQ(0U, candidate_list.size());
474 TEST_F(SingleOverlayOnTopTest, RejectBlending) {
475 scoped_ptr<RenderPass> pass = CreateRenderPass();
476 TextureDrawQuad* quad =
477 CreateFullscreenCandidateQuad(resource_provider_.get(),
478 pass->shared_quad_state_list.back(),
479 pass.get());
480 quad->needs_blending = true;
482 RenderPassList pass_list;
483 pass_list.push_back(pass.Pass());
484 OverlayCandidateList candidate_list;
485 overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
486 ASSERT_EQ(1U, pass_list.size());
487 EXPECT_EQ(0U, candidate_list.size());
490 TEST_F(SingleOverlayOnTopTest, RejectBackgroundColor) {
491 scoped_ptr<RenderPass> pass = CreateRenderPass();
492 TextureDrawQuad* quad =
493 CreateFullscreenCandidateQuad(resource_provider_.get(),
494 pass->shared_quad_state_list.back(),
495 pass.get());
496 quad->background_color = SK_ColorBLACK;
498 RenderPassList pass_list;
499 pass_list.push_back(pass.Pass());
500 OverlayCandidateList candidate_list;
501 overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
502 ASSERT_EQ(1U, pass_list.size());
503 EXPECT_EQ(0U, candidate_list.size());
506 TEST_F(SingleOverlayOnTopTest, RejectBlendMode) {
507 scoped_ptr<RenderPass> pass = CreateRenderPass();
508 CreateFullscreenCandidateQuad(resource_provider_.get(),
509 pass->shared_quad_state_list.back(),
510 pass.get());
511 pass->shared_quad_state_list.back()->blend_mode = SkXfermode::kScreen_Mode;
513 RenderPassList pass_list;
514 pass_list.push_back(pass.Pass());
515 OverlayCandidateList candidate_list;
516 overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
517 ASSERT_EQ(1U, pass_list.size());
518 EXPECT_EQ(0U, candidate_list.size());
521 TEST_F(SingleOverlayOnTopTest, RejectOpacity) {
522 scoped_ptr<RenderPass> pass = CreateRenderPass();
523 CreateFullscreenCandidateQuad(resource_provider_.get(),
524 pass->shared_quad_state_list.back(),
525 pass.get());
526 pass->shared_quad_state_list.back()->opacity = 0.5f;
528 RenderPassList pass_list;
529 pass_list.push_back(pass.Pass());
530 OverlayCandidateList candidate_list;
531 overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
532 ASSERT_EQ(1U, pass_list.size());
533 EXPECT_EQ(0U, candidate_list.size());
536 TEST_F(SingleOverlayOnTopTest, RejectNonScaleTransform) {
537 scoped_ptr<RenderPass> pass = CreateRenderPass();
538 CreateFullscreenCandidateQuad(resource_provider_.get(),
539 pass->shared_quad_state_list.back(),
540 pass.get());
541 pass->shared_quad_state_list.back()
542 ->content_to_target_transform.RotateAboutXAxis(45.f);
544 RenderPassList pass_list;
545 pass_list.push_back(pass.Pass());
546 OverlayCandidateList candidate_list;
547 overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
548 ASSERT_EQ(1U, pass_list.size());
549 EXPECT_EQ(0U, candidate_list.size());
552 TEST_F(SingleOverlayOnTopTest, RejectNegativeScaleTransform) {
553 scoped_ptr<RenderPass> pass = CreateRenderPass();
554 CreateFullscreenCandidateQuad(resource_provider_.get(),
555 pass->shared_quad_state_list.back(),
556 pass.get());
557 pass->shared_quad_state_list.back()->content_to_target_transform.Scale(2.0f,
558 -1.0f);
560 RenderPassList pass_list;
561 pass_list.push_back(pass.Pass());
562 OverlayCandidateList candidate_list;
563 overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
564 ASSERT_EQ(1U, pass_list.size());
565 EXPECT_EQ(0U, candidate_list.size());
568 TEST_F(SingleOverlayOnTopTest, AllowPositiveScaleTransform) {
569 gfx::Rect rect = kOverlayRect;
570 rect.set_width(rect.width() / 2);
571 scoped_ptr<RenderPass> pass = CreateRenderPass();
572 CreateCandidateQuadAt(resource_provider_.get(),
573 pass->shared_quad_state_list.back(), pass.get(), rect);
574 pass->shared_quad_state_list.back()->content_to_target_transform.Scale(2.0f,
575 1.0f);
577 RenderPassList pass_list;
578 pass_list.push_back(pass.Pass());
579 OverlayCandidateList candidate_list;
580 overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
581 ASSERT_EQ(1U, pass_list.size());
582 EXPECT_EQ(2U, candidate_list.size());
585 TEST_F(SingleOverlayOnTopTest, AllowNotTopIfNotOccluded) {
586 scoped_ptr<RenderPass> pass = CreateRenderPass();
587 CreateCheckeredQuadAt(resource_provider_.get(),
588 pass->shared_quad_state_list.back(),
589 pass.get(),
590 kOverlayTopLeftRect);
591 CreateCandidateQuadAt(resource_provider_.get(),
592 pass->shared_quad_state_list.back(),
593 pass.get(),
594 kOverlayBottomRightRect);
596 RenderPassList pass_list;
597 pass_list.push_back(pass.Pass());
599 RenderPassList original_pass_list;
600 RenderPass::CopyAll(pass_list, &original_pass_list);
602 OverlayCandidateList candidate_list;
603 overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
604 EXPECT_EQ(1U, pass_list.size());
605 EXPECT_EQ(2U, candidate_list.size());
608 TEST_F(SingleOverlayOnTopTest, AllowTransparentOnTop) {
609 scoped_ptr<RenderPass> pass = CreateRenderPass();
610 SharedQuadState* shared_state = pass->CreateAndAppendSharedQuadState();
611 shared_state->opacity = 0.f;
612 CreateSolidColorQuadAt(shared_state, SK_ColorBLACK, pass.get(),
613 kOverlayBottomRightRect);
614 shared_state = pass->CreateAndAppendSharedQuadState();
615 shared_state->opacity = 1.f;
616 CreateCandidateQuadAt(resource_provider_.get(), shared_state, pass.get(),
617 kOverlayBottomRightRect);
619 RenderPassList pass_list;
620 pass_list.push_back(pass.Pass());
622 RenderPassList original_pass_list;
623 RenderPass::CopyAll(pass_list, &original_pass_list);
625 OverlayCandidateList candidate_list;
626 overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
627 EXPECT_EQ(1U, pass_list.size());
628 EXPECT_EQ(2U, candidate_list.size());
631 TEST_F(SingleOverlayOnTopTest, AllowTransparentColorOnTop) {
632 scoped_ptr<RenderPass> pass = CreateRenderPass();
633 CreateSolidColorQuadAt(pass->shared_quad_state_list.back(),
634 SK_ColorTRANSPARENT, pass.get(),
635 kOverlayBottomRightRect);
636 CreateCandidateQuadAt(resource_provider_.get(),
637 pass->shared_quad_state_list.back(), pass.get(),
638 kOverlayBottomRightRect);
640 RenderPassList pass_list;
641 pass_list.push_back(pass.Pass());
643 RenderPassList original_pass_list;
644 RenderPass::CopyAll(pass_list, &original_pass_list);
646 OverlayCandidateList candidate_list;
647 overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
648 EXPECT_EQ(1U, pass_list.size());
649 EXPECT_EQ(2U, candidate_list.size());
652 TEST_F(SingleOverlayOnTopTest, RejectOpaqueColorOnTop) {
653 scoped_ptr<RenderPass> pass = CreateRenderPass();
654 SharedQuadState* shared_state = pass->CreateAndAppendSharedQuadState();
655 shared_state->opacity = 0.5f;
656 CreateSolidColorQuadAt(shared_state, SK_ColorBLACK, pass.get(),
657 kOverlayBottomRightRect);
658 shared_state = pass->CreateAndAppendSharedQuadState();
659 shared_state->opacity = 1.f;
660 CreateCandidateQuadAt(resource_provider_.get(), shared_state, pass.get(),
661 kOverlayBottomRightRect);
663 RenderPassList pass_list;
664 pass_list.push_back(pass.Pass());
666 RenderPassList original_pass_list;
667 RenderPass::CopyAll(pass_list, &original_pass_list);
669 OverlayCandidateList candidate_list;
670 overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
671 EXPECT_EQ(1U, pass_list.size());
672 EXPECT_EQ(0U, candidate_list.size());
675 TEST_F(SingleOverlayOnTopTest, RejectTransparentColorOnTopWithoutBlending) {
676 scoped_ptr<RenderPass> pass = CreateRenderPass();
677 SharedQuadState* shared_state = pass->CreateAndAppendSharedQuadState();
678 CreateSolidColorQuadAt(shared_state, SK_ColorTRANSPARENT, pass.get(),
679 kOverlayBottomRightRect)->opaque_rect =
680 kOverlayBottomRightRect;
681 CreateCandidateQuadAt(resource_provider_.get(), shared_state, pass.get(),
682 kOverlayBottomRightRect);
684 RenderPassList pass_list;
685 pass_list.push_back(pass.Pass());
687 RenderPassList original_pass_list;
688 RenderPass::CopyAll(pass_list, &original_pass_list);
690 OverlayCandidateList candidate_list;
691 overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
692 EXPECT_EQ(1U, pass_list.size());
693 EXPECT_EQ(0U, candidate_list.size());
696 TEST_F(SingleOverlayOnTopTest, RejectVideoSwapTransform) {
697 scoped_ptr<RenderPass> pass = CreateRenderPass();
698 CreateFullscreenCandidateVideoQuad(resource_provider_.get(),
699 pass->shared_quad_state_list.back(),
700 pass.get(), kSwapTransform);
702 RenderPassList pass_list;
703 pass_list.push_back(pass.Pass());
704 OverlayCandidateList candidate_list;
705 overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
706 ASSERT_EQ(1U, pass_list.size());
707 EXPECT_EQ(0U, candidate_list.size());
710 TEST_F(SingleOverlayOnTopTest, AllowVideoXMirrorTransform) {
711 scoped_ptr<RenderPass> pass = CreateRenderPass();
712 CreateFullscreenCandidateVideoQuad(resource_provider_.get(),
713 pass->shared_quad_state_list.back(),
714 pass.get(), kXMirrorTransform);
716 RenderPassList pass_list;
717 pass_list.push_back(pass.Pass());
718 OverlayCandidateList candidate_list;
719 overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
720 ASSERT_EQ(1U, pass_list.size());
721 EXPECT_EQ(2U, candidate_list.size());
724 TEST_F(SingleOverlayOnTopTest, AllowVideoBothMirrorTransform) {
725 scoped_ptr<RenderPass> pass = CreateRenderPass();
726 CreateFullscreenCandidateVideoQuad(resource_provider_.get(),
727 pass->shared_quad_state_list.back(),
728 pass.get(), kBothMirrorTransform);
730 RenderPassList pass_list;
731 pass_list.push_back(pass.Pass());
732 OverlayCandidateList candidate_list;
733 overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
734 ASSERT_EQ(1U, pass_list.size());
735 EXPECT_EQ(2U, candidate_list.size());
738 TEST_F(SingleOverlayOnTopTest, AllowVideoNormalTransform) {
739 scoped_ptr<RenderPass> pass = CreateRenderPass();
740 CreateFullscreenCandidateVideoQuad(resource_provider_.get(),
741 pass->shared_quad_state_list.back(),
742 pass.get(), kNormalTransform);
744 RenderPassList pass_list;
745 pass_list.push_back(pass.Pass());
746 OverlayCandidateList candidate_list;
747 overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
748 ASSERT_EQ(1U, pass_list.size());
749 EXPECT_EQ(2U, candidate_list.size());
752 TEST_F(SingleOverlayOnTopTest, AllowVideoYMirrorTransform) {
753 scoped_ptr<RenderPass> pass = CreateRenderPass();
754 CreateFullscreenCandidateVideoQuad(resource_provider_.get(),
755 pass->shared_quad_state_list.back(),
756 pass.get(), kYMirrorTransform);
758 RenderPassList pass_list;
759 pass_list.push_back(pass.Pass());
760 OverlayCandidateList candidate_list;
761 overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
762 ASSERT_EQ(1U, pass_list.size());
763 EXPECT_EQ(2U, candidate_list.size());
766 TEST_F(UnderlayTest, OverlayLayerUnderMainLayer) {
767 scoped_ptr<RenderPass> pass = CreateRenderPass();
768 CreateFullscreenCheckeredQuad(resource_provider_.get(),
769 pass->shared_quad_state_list.back(),
770 pass.get());
771 CreateCandidateQuadAt(resource_provider_.get(),
772 pass->shared_quad_state_list.back(), pass.get(),
773 kOverlayBottomRightRect);
775 RenderPassList pass_list;
776 pass_list.push_back(pass.Pass());
778 OverlayCandidateList candidate_list;
779 overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
780 EXPECT_EQ(1U, pass_list.size());
781 ASSERT_EQ(2U, candidate_list.size());
782 EXPECT_EQ(0, candidate_list[0].plane_z_order);
783 EXPECT_EQ(-1, candidate_list[1].plane_z_order);
784 EXPECT_EQ(2U, pass_list[0]->quad_list.size());
785 // The overlay quad should have changed to a SOLID_COLOR quad.
786 EXPECT_EQ(pass_list[0]->quad_list.back()->material, DrawQuad::SOLID_COLOR);
789 TEST_F(UnderlayTest, AllowOnTop) {
790 scoped_ptr<RenderPass> pass = CreateRenderPass();
791 CreateFullscreenCandidateQuad(resource_provider_.get(),
792 pass->shared_quad_state_list.back(),
793 pass.get());
794 pass->CreateAndAppendSharedQuadState()->opacity = 0.5f;
795 CreateFullscreenCheckeredQuad(resource_provider_.get(),
796 pass->shared_quad_state_list.back(),
797 pass.get());
799 RenderPassList pass_list;
800 pass_list.push_back(pass.Pass());
802 OverlayCandidateList candidate_list;
803 overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
804 EXPECT_EQ(1U, pass_list.size());
805 ASSERT_EQ(2U, candidate_list.size());
806 EXPECT_EQ(0, candidate_list[0].plane_z_order);
807 EXPECT_EQ(-1, candidate_list[1].plane_z_order);
808 // The overlay quad should have changed to a SOLID_COLOR quad.
809 EXPECT_EQ(pass_list[0]->quad_list.front()->material, DrawQuad::SOLID_COLOR);
812 class OverlayInfoRendererGL : public GLRenderer {
813 public:
814 OverlayInfoRendererGL(RendererClient* client,
815 const RendererSettings* settings,
816 OutputSurface* output_surface,
817 ResourceProvider* resource_provider)
818 : GLRenderer(client,
819 settings,
820 output_surface,
821 resource_provider,
822 NULL,
824 expect_overlays_(false) {}
826 MOCK_METHOD3(DoDrawQuad,
827 void(DrawingFrame* frame,
828 const DrawQuad* quad,
829 const gfx::QuadF* draw_region));
831 using GLRenderer::BeginDrawingFrame;
833 void FinishDrawingFrame(DrawingFrame* frame) override {
834 GLRenderer::FinishDrawingFrame(frame);
836 if (!expect_overlays_) {
837 EXPECT_EQ(0U, frame->overlay_list.size());
838 return;
841 ASSERT_EQ(2U, frame->overlay_list.size());
842 EXPECT_NE(0U, frame->overlay_list.back().resource_id);
845 void set_expect_overlays(bool expect_overlays) {
846 expect_overlays_ = expect_overlays;
849 private:
850 bool expect_overlays_;
853 class FakeRendererClient : public RendererClient {
854 public:
855 // RendererClient methods.
856 void SetFullRootLayerDamage() override {}
859 class MockOverlayScheduler {
860 public:
861 MOCK_METHOD5(Schedule,
862 void(int plane_z_order,
863 gfx::OverlayTransform plane_transform,
864 unsigned overlay_texture_id,
865 const gfx::Rect& display_bounds,
866 const gfx::RectF& uv_rect));
869 class GLRendererWithOverlaysTest : public testing::Test {
870 protected:
871 GLRendererWithOverlaysTest() {
872 provider_ = TestContextProvider::Create();
873 output_surface_.reset(new OverlayOutputSurface(provider_));
874 CHECK(output_surface_->BindToClient(&output_surface_client_));
875 resource_provider_ = ResourceProvider::Create(
876 output_surface_.get(), NULL, NULL, NULL, 0, false, 1);
878 provider_->support()->SetScheduleOverlayPlaneCallback(base::Bind(
879 &MockOverlayScheduler::Schedule, base::Unretained(&scheduler_)));
882 void Init(bool use_validator) {
883 if (use_validator)
884 output_surface_->InitWithSingleOverlayValidator();
886 renderer_ =
887 make_scoped_ptr(new OverlayInfoRendererGL(&renderer_client_,
888 &settings_,
889 output_surface_.get(),
890 resource_provider_.get()));
893 void SwapBuffers() { renderer_->SwapBuffers(CompositorFrameMetadata()); }
895 RendererSettings settings_;
896 FakeOutputSurfaceClient output_surface_client_;
897 scoped_ptr<OverlayOutputSurface> output_surface_;
898 FakeRendererClient renderer_client_;
899 scoped_ptr<ResourceProvider> resource_provider_;
900 scoped_ptr<OverlayInfoRendererGL> renderer_;
901 scoped_refptr<TestContextProvider> provider_;
902 MockOverlayScheduler scheduler_;
905 TEST_F(GLRendererWithOverlaysTest, OverlayQuadNotDrawn) {
906 bool use_validator = true;
907 Init(use_validator);
908 renderer_->set_expect_overlays(true);
909 gfx::Rect viewport_rect(16, 16);
911 scoped_ptr<RenderPass> pass = CreateRenderPass();
913 CreateFullscreenCandidateQuad(resource_provider_.get(),
914 pass->shared_quad_state_list.back(),
915 pass.get());
917 CreateFullscreenCheckeredQuad(resource_provider_.get(),
918 pass->shared_quad_state_list.back(),
919 pass.get());
920 CreateFullscreenCheckeredQuad(resource_provider_.get(),
921 pass->shared_quad_state_list.back(),
922 pass.get());
924 RenderPassList pass_list;
925 pass_list.push_back(pass.Pass());
927 // Candidate pass was taken out and extra skipped pass added,
928 // so only draw 2 quads.
929 EXPECT_CALL(*renderer_, DoDrawQuad(_, _, _)).Times(2);
930 EXPECT_CALL(scheduler_,
931 Schedule(1,
932 gfx::OVERLAY_TRANSFORM_NONE,
934 kOverlayRect,
935 BoundingRect(kUVTopLeft, kUVBottomRight))).Times(1);
936 renderer_->DrawFrame(&pass_list, 1.f, viewport_rect, viewport_rect, false);
938 SwapBuffers();
940 Mock::VerifyAndClearExpectations(renderer_.get());
941 Mock::VerifyAndClearExpectations(&scheduler_);
944 TEST_F(GLRendererWithOverlaysTest, OccludedQuadDrawn) {
945 bool use_validator = true;
946 Init(use_validator);
947 renderer_->set_expect_overlays(false);
948 gfx::Rect viewport_rect(16, 16);
950 scoped_ptr<RenderPass> pass = CreateRenderPass();
952 CreateFullscreenCheckeredQuad(resource_provider_.get(),
953 pass->shared_quad_state_list.back(),
954 pass.get());
955 CreateFullscreenCheckeredQuad(resource_provider_.get(),
956 pass->shared_quad_state_list.back(),
957 pass.get());
959 CreateFullscreenCandidateQuad(resource_provider_.get(),
960 pass->shared_quad_state_list.back(),
961 pass.get());
963 RenderPassList pass_list;
964 pass_list.push_back(pass.Pass());
966 // 3 quads in the pass, all should draw.
967 EXPECT_CALL(*renderer_, DoDrawQuad(_, _, _)).Times(3);
968 EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(0);
969 renderer_->DrawFrame(&pass_list, 1.f, viewport_rect, viewport_rect, false);
971 SwapBuffers();
973 Mock::VerifyAndClearExpectations(renderer_.get());
974 Mock::VerifyAndClearExpectations(&scheduler_);
977 TEST_F(GLRendererWithOverlaysTest, NoValidatorNoOverlay) {
978 bool use_validator = false;
979 Init(use_validator);
980 renderer_->set_expect_overlays(false);
981 gfx::Rect viewport_rect(16, 16);
983 scoped_ptr<RenderPass> pass = CreateRenderPass();
985 CreateFullscreenCandidateQuad(resource_provider_.get(),
986 pass->shared_quad_state_list.back(),
987 pass.get());
989 CreateFullscreenCheckeredQuad(resource_provider_.get(),
990 pass->shared_quad_state_list.back(),
991 pass.get());
992 CreateFullscreenCheckeredQuad(resource_provider_.get(),
993 pass->shared_quad_state_list.back(),
994 pass.get());
996 RenderPassList pass_list;
997 pass_list.push_back(pass.Pass());
999 // Should see no overlays.
1000 EXPECT_CALL(*renderer_, DoDrawQuad(_, _, _)).Times(3);
1001 EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(0);
1002 renderer_->DrawFrame(&pass_list, 1.f, viewport_rect, viewport_rect, false);
1004 SwapBuffers();
1006 Mock::VerifyAndClearExpectations(renderer_.get());
1007 Mock::VerifyAndClearExpectations(&scheduler_);
1010 TEST_F(GLRendererWithOverlaysTest, ResourcesExportedAndReturned) {
1011 bool use_validator = true;
1012 Init(use_validator);
1013 renderer_->set_expect_overlays(true);
1015 ResourceProvider::ResourceId resource1 =
1016 CreateResource(resource_provider_.get());
1017 ResourceProvider::ResourceId resource2 =
1018 CreateResource(resource_provider_.get());
1020 scoped_ptr<RenderPass> pass = CreateRenderPass();
1021 RenderPassList pass_list;
1022 pass_list.push_back(pass.Pass());
1024 DirectRenderer::DrawingFrame frame1;
1025 frame1.render_passes_in_draw_order = &pass_list;
1026 frame1.overlay_list.resize(2);
1027 OverlayCandidate& overlay1 = frame1.overlay_list.back();
1028 overlay1.resource_id = resource1;
1029 overlay1.plane_z_order = 1;
1031 DirectRenderer::DrawingFrame frame2;
1032 frame2.render_passes_in_draw_order = &pass_list;
1033 frame2.overlay_list.resize(2);
1034 OverlayCandidate& overlay2 = frame2.overlay_list.back();
1035 overlay2.resource_id = resource2;
1036 overlay2.plane_z_order = 1;
1038 EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(1);
1039 renderer_->BeginDrawingFrame(&frame1);
1040 renderer_->FinishDrawingFrame(&frame1);
1041 EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
1042 EXPECT_FALSE(resource_provider_->InUseByConsumer(resource2));
1043 SwapBuffers();
1044 Mock::VerifyAndClearExpectations(&scheduler_);
1046 EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(1);
1047 renderer_->BeginDrawingFrame(&frame2);
1048 renderer_->FinishDrawingFrame(&frame2);
1049 EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
1050 EXPECT_TRUE(resource_provider_->InUseByConsumer(resource2));
1051 SwapBuffers();
1052 EXPECT_FALSE(resource_provider_->InUseByConsumer(resource1));
1053 Mock::VerifyAndClearExpectations(&scheduler_);
1055 EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(1);
1056 renderer_->BeginDrawingFrame(&frame1);
1057 renderer_->FinishDrawingFrame(&frame1);
1058 EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
1059 EXPECT_TRUE(resource_provider_->InUseByConsumer(resource2));
1060 SwapBuffers();
1061 EXPECT_FALSE(resource_provider_->InUseByConsumer(resource2));
1062 Mock::VerifyAndClearExpectations(&scheduler_);
1064 // No overlays, release the resource.
1065 EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(0);
1066 DirectRenderer::DrawingFrame frame3;
1067 frame3.render_passes_in_draw_order = &pass_list;
1068 renderer_->set_expect_overlays(false);
1069 renderer_->BeginDrawingFrame(&frame3);
1070 renderer_->FinishDrawingFrame(&frame3);
1071 EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
1072 EXPECT_FALSE(resource_provider_->InUseByConsumer(resource2));
1073 SwapBuffers();
1074 EXPECT_FALSE(resource_provider_->InUseByConsumer(resource1));
1075 Mock::VerifyAndClearExpectations(&scheduler_);
1077 // Use the same buffer twice.
1078 renderer_->set_expect_overlays(true);
1079 EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(1);
1080 renderer_->BeginDrawingFrame(&frame1);
1081 renderer_->FinishDrawingFrame(&frame1);
1082 EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
1083 SwapBuffers();
1084 Mock::VerifyAndClearExpectations(&scheduler_);
1086 EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(1);
1087 renderer_->BeginDrawingFrame(&frame1);
1088 renderer_->FinishDrawingFrame(&frame1);
1089 EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
1090 SwapBuffers();
1091 EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
1092 Mock::VerifyAndClearExpectations(&scheduler_);
1094 EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(0);
1095 renderer_->set_expect_overlays(false);
1096 renderer_->BeginDrawingFrame(&frame3);
1097 renderer_->FinishDrawingFrame(&frame3);
1098 EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
1099 SwapBuffers();
1100 EXPECT_FALSE(resource_provider_->InUseByConsumer(resource1));
1101 Mock::VerifyAndClearExpectations(&scheduler_);
1104 } // namespace
1105 } // namespace cc