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/gl_renderer.h"
7 #include "cc/output/output_surface.h"
8 #include "cc/output/output_surface_client.h"
9 #include "cc/output/overlay_candidate_validator.h"
10 #include "cc/output/overlay_processor.h"
11 #include "cc/output/overlay_strategy_single_on_top.h"
12 #include "cc/quads/checkerboard_draw_quad.h"
13 #include "cc/quads/render_pass.h"
14 #include "cc/quads/stream_video_draw_quad.h"
15 #include "cc/quads/texture_draw_quad.h"
16 #include "cc/resources/resource_provider.h"
17 #include "cc/resources/texture_mailbox.h"
18 #include "cc/test/fake_output_surface_client.h"
19 #include "cc/test/geometry_test_utils.h"
20 #include "cc/test/test_context_provider.h"
21 #include "cc/test/test_shared_bitmap_manager.h"
22 #include "testing/gmock/include/gmock/gmock.h"
23 #include "testing/gtest/include/gtest/gtest.h"
31 const gfx::Rect
kOverlayRect(0, 0, 128, 128);
32 const gfx::Rect
kOverlayTopLeftRect(0, 0, 64, 64);
33 const gfx::Rect
kOverlayBottomRightRect(64, 64, 64, 64);
34 const gfx::PointF
kUVTopLeft(0.1f
, 0.2f
);
35 const gfx::PointF
kUVBottomRight(1.0f
, 1.0f
);
36 const gfx::Transform kNormalTransform
=
37 gfx::Transform(0.9f
, 0, 0, 0.8f
, 0.1f
, 0.2f
); // x,y -> x,y.
38 const gfx::Transform kXMirrorTransform
=
39 gfx::Transform(-0.9f
, 0, 0, 0.8f
, 1.0f
, 0.2f
); // x,y -> 1-x,y.
40 const gfx::Transform kYMirrorTransform
=
41 gfx::Transform(0.9f
, 0, 0, -0.8f
, 0.1f
, 1.0f
); // x,y -> x,1-y.
42 const gfx::Transform kBothMirrorTransform
=
43 gfx::Transform(-0.9f
, 0, 0, -0.8f
, 1.0f
, 1.0f
); // x,y -> 1-x,1-y.
44 const gfx::Transform kSwapTransform
=
45 gfx::Transform(0, 1, 1, 0, 0, 0); // x,y -> y,x.
47 void MailboxReleased(unsigned sync_point
,
49 BlockingTaskRunner
* main_thread_task_runner
) {
52 class SingleOverlayValidator
: public OverlayCandidateValidator
{
54 void CheckOverlaySupport(OverlayCandidateList
* surfaces
) override
;
57 void SingleOverlayValidator::CheckOverlaySupport(
58 OverlayCandidateList
* surfaces
) {
59 ASSERT_EQ(2U, surfaces
->size());
61 OverlayCandidate
& candidate
= surfaces
->back();
62 if (candidate
.display_rect
.width() == 64)
63 EXPECT_EQ(kOverlayBottomRightRect
, candidate
.display_rect
);
65 EXPECT_EQ(kOverlayRect
, candidate
.display_rect
);
66 EXPECT_EQ(BoundingRect(kUVTopLeft
, kUVBottomRight
).ToString(),
67 candidate
.uv_rect
.ToString());
68 candidate
.overlay_handled
= true;
71 class SingleOverlayProcessor
: public OverlayProcessor
{
73 SingleOverlayProcessor(OutputSurface
* surface
,
74 ResourceProvider
* resource_provider
);
75 // Virtual to allow testing different strategies.
76 void Initialize() override
;
79 SingleOverlayProcessor::SingleOverlayProcessor(
80 OutputSurface
* surface
,
81 ResourceProvider
* resource_provider
)
82 : OverlayProcessor(surface
, resource_provider
) {
83 EXPECT_EQ(surface
, surface_
);
84 EXPECT_EQ(resource_provider
, resource_provider_
);
87 void SingleOverlayProcessor::Initialize() {
88 OverlayCandidateValidator
* candidates
=
89 surface_
->overlay_candidate_validator();
90 ASSERT_TRUE(candidates
!= NULL
);
91 strategies_
.push_back(scoped_ptr
<Strategy
>(
92 new OverlayStrategySingleOnTop(candidates
, resource_provider_
)));
95 class DefaultOverlayProcessor
: public OverlayProcessor
{
97 DefaultOverlayProcessor(OutputSurface
* surface
,
98 ResourceProvider
* resource_provider
);
99 size_t GetStrategyCount();
102 DefaultOverlayProcessor::DefaultOverlayProcessor(
103 OutputSurface
* surface
,
104 ResourceProvider
* resource_provider
)
105 : OverlayProcessor(surface
, resource_provider
) {}
107 size_t DefaultOverlayProcessor::GetStrategyCount() {
108 return strategies_
.size();
111 class OverlayOutputSurface
: public OutputSurface
{
113 explicit OverlayOutputSurface(scoped_refptr
<ContextProvider
> context_provider
)
114 : OutputSurface(context_provider
) {}
116 // OutputSurface implementation
117 void SwapBuffers(CompositorFrame
* frame
) override
;
119 void InitWithSingleOverlayValidator() {
120 overlay_candidate_validator_
.reset(new SingleOverlayValidator
);
124 void OverlayOutputSurface::SwapBuffers(CompositorFrame
* frame
) {
125 client_
->DidSwapBuffers();
126 client_
->DidSwapBuffersComplete();
129 scoped_ptr
<RenderPass
> CreateRenderPass() {
130 RenderPassId
id(1, 0);
131 gfx::Rect
output_rect(0, 0, 256, 256);
132 bool has_transparent_background
= true;
134 scoped_ptr
<RenderPass
> pass
= RenderPass::Create();
139 has_transparent_background
);
141 SharedQuadState
* shared_state
= pass
->CreateAndAppendSharedQuadState();
142 shared_state
->opacity
= 1.f
;
146 ResourceProvider::ResourceId
CreateResource(
147 ResourceProvider
* resource_provider
) {
148 unsigned sync_point
= 0;
149 TextureMailbox mailbox
=
150 TextureMailbox(gpu::Mailbox::Generate(), GL_TEXTURE_2D
, sync_point
);
151 mailbox
.set_allow_overlay(true);
152 scoped_ptr
<SingleReleaseCallbackImpl
> release_callback
=
153 SingleReleaseCallbackImpl::Create(base::Bind(&MailboxReleased
));
155 return resource_provider
->CreateResourceFromTextureMailbox(
156 mailbox
, release_callback
.Pass());
159 SolidColorDrawQuad
* CreateSolidColorQuadAt(
160 const SharedQuadState
* shared_quad_state
,
162 RenderPass
* render_pass
,
163 const gfx::Rect
& rect
) {
164 SolidColorDrawQuad
* quad
=
165 render_pass
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
166 quad
->SetNew(shared_quad_state
, rect
, rect
, color
, false);
170 TextureDrawQuad
* CreateCandidateQuadAt(ResourceProvider
* resource_provider
,
171 const SharedQuadState
* shared_quad_state
,
172 RenderPass
* render_pass
,
173 const gfx::Rect
& rect
) {
174 ResourceProvider::ResourceId resource_id
= CreateResource(resource_provider
);
175 bool premultiplied_alpha
= false;
176 bool flipped
= false;
177 bool nearest_neighbor
= false;
178 float vertex_opacity
[4] = {1.0f
, 1.0f
, 1.0f
, 1.0f
};
180 TextureDrawQuad
* overlay_quad
=
181 render_pass
->CreateAndAppendDrawQuad
<TextureDrawQuad
>();
182 overlay_quad
->SetNew(shared_quad_state
,
198 StreamVideoDrawQuad
* CreateCandidateVideoQuadAt(
199 ResourceProvider
* resource_provider
,
200 const SharedQuadState
* shared_quad_state
,
201 RenderPass
* render_pass
,
202 const gfx::Rect
& rect
,
203 const gfx::Transform
& transform
) {
204 ResourceProvider::ResourceId resource_id
= CreateResource(resource_provider
);
206 StreamVideoDrawQuad
* overlay_quad
=
207 render_pass
->CreateAndAppendDrawQuad
<StreamVideoDrawQuad
>();
208 overlay_quad
->SetNew(shared_quad_state
, rect
, rect
, rect
, resource_id
,
214 TextureDrawQuad
* CreateFullscreenCandidateQuad(
215 ResourceProvider
* resource_provider
,
216 const SharedQuadState
* shared_quad_state
,
217 RenderPass
* render_pass
) {
218 return CreateCandidateQuadAt(
219 resource_provider
, shared_quad_state
, render_pass
, kOverlayRect
);
222 StreamVideoDrawQuad
* CreateFullscreenCandidateVideoQuad(
223 ResourceProvider
* resource_provider
,
224 const SharedQuadState
* shared_quad_state
,
225 RenderPass
* render_pass
,
226 const gfx::Transform
& transform
) {
227 return CreateCandidateVideoQuadAt(resource_provider
, shared_quad_state
,
228 render_pass
, kOverlayRect
, transform
);
231 void CreateCheckeredQuadAt(ResourceProvider
* resource_provider
,
232 const SharedQuadState
* shared_quad_state
,
233 RenderPass
* render_pass
,
234 const gfx::Rect
& rect
) {
235 CheckerboardDrawQuad
* checkerboard_quad
=
236 render_pass
->CreateAndAppendDrawQuad
<CheckerboardDrawQuad
>();
237 checkerboard_quad
->SetNew(shared_quad_state
, rect
, rect
, SkColor(), 1.f
);
240 void CreateFullscreenCheckeredQuad(ResourceProvider
* resource_provider
,
241 const SharedQuadState
* shared_quad_state
,
242 RenderPass
* render_pass
) {
243 CreateCheckeredQuadAt(
244 resource_provider
, shared_quad_state
, render_pass
, kOverlayRect
);
247 static void CompareRenderPassLists(const RenderPassList
& expected_list
,
248 const RenderPassList
& actual_list
) {
249 EXPECT_EQ(expected_list
.size(), actual_list
.size());
250 for (size_t i
= 0; i
< actual_list
.size(); ++i
) {
251 RenderPass
* expected
= expected_list
[i
];
252 RenderPass
* actual
= actual_list
[i
];
254 EXPECT_EQ(expected
->id
, actual
->id
);
255 EXPECT_EQ(expected
->output_rect
, actual
->output_rect
);
256 EXPECT_EQ(expected
->transform_to_root_target
,
257 actual
->transform_to_root_target
);
258 EXPECT_EQ(expected
->damage_rect
, actual
->damage_rect
);
259 EXPECT_EQ(expected
->has_transparent_background
,
260 actual
->has_transparent_background
);
262 EXPECT_EQ(expected
->shared_quad_state_list
.size(),
263 actual
->shared_quad_state_list
.size());
264 EXPECT_EQ(expected
->quad_list
.size(), actual
->quad_list
.size());
266 for (auto exp_iter
= expected
->quad_list
.cbegin(),
267 act_iter
= actual
->quad_list
.cbegin();
268 exp_iter
!= expected
->quad_list
.cend();
269 ++exp_iter
, ++act_iter
) {
270 EXPECT_EQ(exp_iter
->rect
.ToString(), act_iter
->rect
.ToString());
271 EXPECT_EQ(exp_iter
->shared_quad_state
->content_bounds
.ToString(),
272 act_iter
->shared_quad_state
->content_bounds
.ToString());
277 TEST(OverlayTest
, NoOverlaysByDefault
) {
278 scoped_refptr
<TestContextProvider
> provider
= TestContextProvider::Create();
279 OverlayOutputSurface
output_surface(provider
);
280 EXPECT_EQ(NULL
, output_surface
.overlay_candidate_validator());
282 output_surface
.InitWithSingleOverlayValidator();
283 EXPECT_TRUE(output_surface
.overlay_candidate_validator() != NULL
);
286 TEST(OverlayTest
, OverlaysProcessorHasStrategy
) {
287 scoped_refptr
<TestContextProvider
> provider
= TestContextProvider::Create();
288 OverlayOutputSurface
output_surface(provider
);
289 FakeOutputSurfaceClient client
;
290 EXPECT_TRUE(output_surface
.BindToClient(&client
));
291 output_surface
.InitWithSingleOverlayValidator();
292 EXPECT_TRUE(output_surface
.overlay_candidate_validator() != NULL
);
294 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager(
295 new TestSharedBitmapManager());
296 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
297 &output_surface
, shared_bitmap_manager
.get(), NULL
, NULL
, 0, false, 1));
299 scoped_ptr
<DefaultOverlayProcessor
> overlay_processor(
300 new DefaultOverlayProcessor(&output_surface
, resource_provider
.get()));
301 overlay_processor
->Initialize();
302 EXPECT_GE(1U, overlay_processor
->GetStrategyCount());
305 class SingleOverlayOnTopTest
: public testing::Test
{
307 void SetUp() override
{
308 provider_
= TestContextProvider::Create();
309 output_surface_
.reset(new OverlayOutputSurface(provider_
));
310 EXPECT_TRUE(output_surface_
->BindToClient(&client_
));
311 output_surface_
->InitWithSingleOverlayValidator();
312 EXPECT_TRUE(output_surface_
->overlay_candidate_validator() != NULL
);
314 shared_bitmap_manager_
.reset(new TestSharedBitmapManager());
315 resource_provider_
= ResourceProvider::Create(output_surface_
.get(),
316 shared_bitmap_manager_
.get(),
323 overlay_processor_
.reset(new SingleOverlayProcessor(
324 output_surface_
.get(), resource_provider_
.get()));
325 overlay_processor_
->Initialize();
328 scoped_refptr
<TestContextProvider
> provider_
;
329 scoped_ptr
<OverlayOutputSurface
> output_surface_
;
330 FakeOutputSurfaceClient client_
;
331 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager_
;
332 scoped_ptr
<ResourceProvider
> resource_provider_
;
333 scoped_ptr
<SingleOverlayProcessor
> overlay_processor_
;
336 TEST_F(SingleOverlayOnTopTest
, SuccessfullOverlay
) {
337 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
338 TextureDrawQuad
* original_quad
=
339 CreateFullscreenCandidateQuad(resource_provider_
.get(),
340 pass
->shared_quad_state_list
.back(),
342 unsigned original_resource_id
= original_quad
->resource_id
;
344 // Add something behind it.
345 CreateFullscreenCheckeredQuad(resource_provider_
.get(),
346 pass
->shared_quad_state_list
.back(),
348 CreateFullscreenCheckeredQuad(resource_provider_
.get(),
349 pass
->shared_quad_state_list
.back(),
352 RenderPassList pass_list
;
353 pass_list
.push_back(pass
.Pass());
355 // Check for potential candidates.
356 OverlayCandidateList candidate_list
;
357 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
359 ASSERT_EQ(1U, pass_list
.size());
360 ASSERT_EQ(2U, candidate_list
.size());
362 RenderPass
* main_pass
= pass_list
.back();
363 // Check that the quad is gone.
364 EXPECT_EQ(2U, main_pass
->quad_list
.size());
365 const QuadList
& quad_list
= main_pass
->quad_list
;
366 for (QuadList::ConstBackToFrontIterator it
= quad_list
.BackToFrontBegin();
367 it
!= quad_list
.BackToFrontEnd();
369 EXPECT_NE(DrawQuad::TEXTURE_CONTENT
, it
->material
);
372 // Check that the right resource id got extracted.
373 EXPECT_EQ(original_resource_id
, candidate_list
.back().resource_id
);
376 TEST_F(SingleOverlayOnTopTest
, NoCandidates
) {
377 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
378 CreateFullscreenCheckeredQuad(resource_provider_
.get(),
379 pass
->shared_quad_state_list
.back(),
381 CreateFullscreenCheckeredQuad(resource_provider_
.get(),
382 pass
->shared_quad_state_list
.back(),
385 RenderPassList pass_list
;
386 pass_list
.push_back(pass
.Pass());
388 RenderPassList original_pass_list
;
389 RenderPass::CopyAll(pass_list
, &original_pass_list
);
391 OverlayCandidateList candidate_list
;
392 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
393 EXPECT_EQ(0U, candidate_list
.size());
394 // There should be nothing new here.
395 CompareRenderPassLists(pass_list
, original_pass_list
);
398 TEST_F(SingleOverlayOnTopTest
, OccludedCandidates
) {
399 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
400 CreateFullscreenCheckeredQuad(resource_provider_
.get(),
401 pass
->shared_quad_state_list
.back(),
403 CreateFullscreenCheckeredQuad(resource_provider_
.get(),
404 pass
->shared_quad_state_list
.back(),
407 CreateFullscreenCandidateQuad(resource_provider_
.get(),
408 pass
->shared_quad_state_list
.back(),
411 RenderPassList pass_list
;
412 pass_list
.push_back(pass
.Pass());
414 RenderPassList original_pass_list
;
415 RenderPass::CopyAll(pass_list
, &original_pass_list
);
417 OverlayCandidateList candidate_list
;
418 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
419 EXPECT_EQ(0U, candidate_list
.size());
420 // There should be nothing new here.
421 CompareRenderPassLists(pass_list
, original_pass_list
);
424 // Test with multiple render passes.
425 TEST_F(SingleOverlayOnTopTest
, MultipleRenderPasses
) {
426 RenderPassList pass_list
;
427 pass_list
.push_back(CreateRenderPass());
429 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
430 CreateFullscreenCandidateQuad(resource_provider_
.get(),
431 pass
->shared_quad_state_list
.back(),
434 // Add something behind it.
435 CreateFullscreenCheckeredQuad(resource_provider_
.get(),
436 pass
->shared_quad_state_list
.back(),
438 CreateFullscreenCheckeredQuad(resource_provider_
.get(),
439 pass
->shared_quad_state_list
.back(),
442 pass_list
.push_back(pass
.Pass());
444 RenderPassList original_pass_list
;
445 RenderPass::CopyAll(pass_list
, &original_pass_list
);
447 // Check for potential candidates.
448 OverlayCandidateList candidate_list
;
449 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
450 EXPECT_EQ(2U, candidate_list
.size());
452 // This should be the same.
453 ASSERT_EQ(2U, pass_list
.size());
456 TEST_F(SingleOverlayOnTopTest
, RejectPremultipliedAlpha
) {
457 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
458 TextureDrawQuad
* quad
=
459 CreateFullscreenCandidateQuad(resource_provider_
.get(),
460 pass
->shared_quad_state_list
.back(),
462 quad
->premultiplied_alpha
= true;
464 RenderPassList pass_list
;
465 pass_list
.push_back(pass
.Pass());
466 OverlayCandidateList candidate_list
;
467 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
468 EXPECT_EQ(1U, pass_list
.size());
469 EXPECT_EQ(0U, candidate_list
.size());
472 TEST_F(SingleOverlayOnTopTest
, RejectBlending
) {
473 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
474 TextureDrawQuad
* quad
=
475 CreateFullscreenCandidateQuad(resource_provider_
.get(),
476 pass
->shared_quad_state_list
.back(),
478 quad
->needs_blending
= true;
480 RenderPassList pass_list
;
481 pass_list
.push_back(pass
.Pass());
482 OverlayCandidateList candidate_list
;
483 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
484 ASSERT_EQ(1U, pass_list
.size());
485 EXPECT_EQ(0U, candidate_list
.size());
488 TEST_F(SingleOverlayOnTopTest
, RejectBackgroundColor
) {
489 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
490 TextureDrawQuad
* quad
=
491 CreateFullscreenCandidateQuad(resource_provider_
.get(),
492 pass
->shared_quad_state_list
.back(),
494 quad
->background_color
= SK_ColorBLACK
;
496 RenderPassList pass_list
;
497 pass_list
.push_back(pass
.Pass());
498 OverlayCandidateList candidate_list
;
499 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
500 ASSERT_EQ(1U, pass_list
.size());
501 EXPECT_EQ(0U, candidate_list
.size());
504 TEST_F(SingleOverlayOnTopTest
, RejectBlendMode
) {
505 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
506 CreateFullscreenCandidateQuad(resource_provider_
.get(),
507 pass
->shared_quad_state_list
.back(),
509 pass
->shared_quad_state_list
.back()->blend_mode
= SkXfermode::kScreen_Mode
;
511 RenderPassList pass_list
;
512 pass_list
.push_back(pass
.Pass());
513 OverlayCandidateList candidate_list
;
514 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
515 ASSERT_EQ(1U, pass_list
.size());
516 EXPECT_EQ(0U, candidate_list
.size());
519 TEST_F(SingleOverlayOnTopTest
, RejectOpacity
) {
520 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
521 CreateFullscreenCandidateQuad(resource_provider_
.get(),
522 pass
->shared_quad_state_list
.back(),
524 pass
->shared_quad_state_list
.back()->opacity
= 0.5f
;
526 RenderPassList pass_list
;
527 pass_list
.push_back(pass
.Pass());
528 OverlayCandidateList candidate_list
;
529 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
530 ASSERT_EQ(1U, pass_list
.size());
531 EXPECT_EQ(0U, candidate_list
.size());
534 TEST_F(SingleOverlayOnTopTest
, RejectNonScaleTransform
) {
535 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
536 CreateFullscreenCandidateQuad(resource_provider_
.get(),
537 pass
->shared_quad_state_list
.back(),
539 pass
->shared_quad_state_list
.back()
540 ->content_to_target_transform
.RotateAboutXAxis(45.f
);
542 RenderPassList pass_list
;
543 pass_list
.push_back(pass
.Pass());
544 OverlayCandidateList candidate_list
;
545 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
546 ASSERT_EQ(1U, pass_list
.size());
547 EXPECT_EQ(0U, candidate_list
.size());
550 TEST_F(SingleOverlayOnTopTest
, RejectNegativeScaleTransform
) {
551 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
552 CreateFullscreenCandidateQuad(resource_provider_
.get(),
553 pass
->shared_quad_state_list
.back(),
555 pass
->shared_quad_state_list
.back()->content_to_target_transform
.Scale(2.0f
,
558 RenderPassList pass_list
;
559 pass_list
.push_back(pass
.Pass());
560 OverlayCandidateList candidate_list
;
561 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
562 ASSERT_EQ(1U, pass_list
.size());
563 EXPECT_EQ(0U, candidate_list
.size());
566 TEST_F(SingleOverlayOnTopTest
, AllowPositiveScaleTransform
) {
567 gfx::Rect rect
= kOverlayRect
;
568 rect
.set_width(rect
.width() / 2);
569 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
570 CreateCandidateQuadAt(resource_provider_
.get(),
571 pass
->shared_quad_state_list
.back(), pass
.get(), rect
);
572 pass
->shared_quad_state_list
.back()->content_to_target_transform
.Scale(2.0f
,
575 RenderPassList pass_list
;
576 pass_list
.push_back(pass
.Pass());
577 OverlayCandidateList candidate_list
;
578 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
579 ASSERT_EQ(1U, pass_list
.size());
580 EXPECT_EQ(2U, candidate_list
.size());
583 TEST_F(SingleOverlayOnTopTest
, AllowNotTopIfNotOccluded
) {
584 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
585 CreateCheckeredQuadAt(resource_provider_
.get(),
586 pass
->shared_quad_state_list
.back(),
588 kOverlayTopLeftRect
);
589 CreateCandidateQuadAt(resource_provider_
.get(),
590 pass
->shared_quad_state_list
.back(),
592 kOverlayBottomRightRect
);
594 RenderPassList pass_list
;
595 pass_list
.push_back(pass
.Pass());
597 RenderPassList original_pass_list
;
598 RenderPass::CopyAll(pass_list
, &original_pass_list
);
600 OverlayCandidateList candidate_list
;
601 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
602 EXPECT_EQ(1U, pass_list
.size());
603 EXPECT_EQ(2U, candidate_list
.size());
606 TEST_F(SingleOverlayOnTopTest
, AllowTransparentOnTop
) {
607 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
608 SharedQuadState
* shared_state
= pass
->CreateAndAppendSharedQuadState();
609 shared_state
->opacity
= 0.f
;
610 CreateSolidColorQuadAt(shared_state
, SK_ColorBLACK
, pass
.get(),
611 kOverlayBottomRightRect
);
612 shared_state
= pass
->CreateAndAppendSharedQuadState();
613 shared_state
->opacity
= 1.f
;
614 CreateCandidateQuadAt(resource_provider_
.get(), shared_state
, pass
.get(),
615 kOverlayBottomRightRect
);
617 RenderPassList pass_list
;
618 pass_list
.push_back(pass
.Pass());
620 RenderPassList original_pass_list
;
621 RenderPass::CopyAll(pass_list
, &original_pass_list
);
623 OverlayCandidateList candidate_list
;
624 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
625 EXPECT_EQ(1U, pass_list
.size());
626 EXPECT_EQ(2U, candidate_list
.size());
629 TEST_F(SingleOverlayOnTopTest
, AllowTransparentColorOnTop
) {
630 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
631 CreateSolidColorQuadAt(pass
->shared_quad_state_list
.back(),
632 SK_ColorTRANSPARENT
, pass
.get(),
633 kOverlayBottomRightRect
);
634 CreateCandidateQuadAt(resource_provider_
.get(),
635 pass
->shared_quad_state_list
.back(), pass
.get(),
636 kOverlayBottomRightRect
);
638 RenderPassList pass_list
;
639 pass_list
.push_back(pass
.Pass());
641 RenderPassList original_pass_list
;
642 RenderPass::CopyAll(pass_list
, &original_pass_list
);
644 OverlayCandidateList candidate_list
;
645 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
646 EXPECT_EQ(1U, pass_list
.size());
647 EXPECT_EQ(2U, candidate_list
.size());
650 TEST_F(SingleOverlayOnTopTest
, RejectOpaqueColorOnTop
) {
651 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
652 SharedQuadState
* shared_state
= pass
->CreateAndAppendSharedQuadState();
653 shared_state
->opacity
= 0.5f
;
654 CreateSolidColorQuadAt(shared_state
, SK_ColorBLACK
, pass
.get(),
655 kOverlayBottomRightRect
);
656 shared_state
= pass
->CreateAndAppendSharedQuadState();
657 shared_state
->opacity
= 1.f
;
658 CreateCandidateQuadAt(resource_provider_
.get(), shared_state
, pass
.get(),
659 kOverlayBottomRightRect
);
661 RenderPassList pass_list
;
662 pass_list
.push_back(pass
.Pass());
664 RenderPassList original_pass_list
;
665 RenderPass::CopyAll(pass_list
, &original_pass_list
);
667 OverlayCandidateList candidate_list
;
668 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
669 EXPECT_EQ(1U, pass_list
.size());
670 EXPECT_EQ(0U, candidate_list
.size());
673 TEST_F(SingleOverlayOnTopTest
, RejectTransparentColorOnTopWithoutBlending
) {
674 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
675 SharedQuadState
* shared_state
= pass
->CreateAndAppendSharedQuadState();
676 CreateSolidColorQuadAt(shared_state
, SK_ColorTRANSPARENT
, pass
.get(),
677 kOverlayBottomRightRect
)->opaque_rect
=
678 kOverlayBottomRightRect
;
679 CreateCandidateQuadAt(resource_provider_
.get(), shared_state
, pass
.get(),
680 kOverlayBottomRightRect
);
682 RenderPassList pass_list
;
683 pass_list
.push_back(pass
.Pass());
685 RenderPassList original_pass_list
;
686 RenderPass::CopyAll(pass_list
, &original_pass_list
);
688 OverlayCandidateList candidate_list
;
689 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
690 EXPECT_EQ(1U, pass_list
.size());
691 EXPECT_EQ(0U, candidate_list
.size());
694 TEST_F(SingleOverlayOnTopTest
, RejectVideoSwapTransform
) {
695 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
696 CreateFullscreenCandidateVideoQuad(resource_provider_
.get(),
697 pass
->shared_quad_state_list
.back(),
698 pass
.get(), kSwapTransform
);
700 RenderPassList pass_list
;
701 pass_list
.push_back(pass
.Pass());
702 OverlayCandidateList candidate_list
;
703 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
704 ASSERT_EQ(1U, pass_list
.size());
705 EXPECT_EQ(0U, candidate_list
.size());
708 TEST_F(SingleOverlayOnTopTest
, AllowVideoXMirrorTransform
) {
709 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
710 CreateFullscreenCandidateVideoQuad(resource_provider_
.get(),
711 pass
->shared_quad_state_list
.back(),
712 pass
.get(), kXMirrorTransform
);
714 RenderPassList pass_list
;
715 pass_list
.push_back(pass
.Pass());
716 OverlayCandidateList candidate_list
;
717 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
718 ASSERT_EQ(1U, pass_list
.size());
719 EXPECT_EQ(2U, candidate_list
.size());
722 TEST_F(SingleOverlayOnTopTest
, AllowVideoBothMirrorTransform
) {
723 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
724 CreateFullscreenCandidateVideoQuad(resource_provider_
.get(),
725 pass
->shared_quad_state_list
.back(),
726 pass
.get(), kBothMirrorTransform
);
728 RenderPassList pass_list
;
729 pass_list
.push_back(pass
.Pass());
730 OverlayCandidateList candidate_list
;
731 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
732 ASSERT_EQ(1U, pass_list
.size());
733 EXPECT_EQ(2U, candidate_list
.size());
736 TEST_F(SingleOverlayOnTopTest
, AllowVideoNormalTransform
) {
737 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
738 CreateFullscreenCandidateVideoQuad(resource_provider_
.get(),
739 pass
->shared_quad_state_list
.back(),
740 pass
.get(), kNormalTransform
);
742 RenderPassList pass_list
;
743 pass_list
.push_back(pass
.Pass());
744 OverlayCandidateList candidate_list
;
745 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
746 ASSERT_EQ(1U, pass_list
.size());
747 EXPECT_EQ(2U, candidate_list
.size());
750 TEST_F(SingleOverlayOnTopTest
, AllowVideoYMirrorTransform
) {
751 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
752 CreateFullscreenCandidateVideoQuad(resource_provider_
.get(),
753 pass
->shared_quad_state_list
.back(),
754 pass
.get(), kYMirrorTransform
);
756 RenderPassList pass_list
;
757 pass_list
.push_back(pass
.Pass());
758 OverlayCandidateList candidate_list
;
759 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
760 ASSERT_EQ(1U, pass_list
.size());
761 EXPECT_EQ(2U, candidate_list
.size());
764 class OverlayInfoRendererGL
: public GLRenderer
{
766 OverlayInfoRendererGL(RendererClient
* client
,
767 const RendererSettings
* settings
,
768 OutputSurface
* output_surface
,
769 ResourceProvider
* resource_provider
)
776 expect_overlays_(false) {}
778 MOCK_METHOD2(DoDrawQuad
, void(DrawingFrame
* frame
, const DrawQuad
* quad
));
780 using GLRenderer::BeginDrawingFrame
;
782 void FinishDrawingFrame(DrawingFrame
* frame
) override
{
783 GLRenderer::FinishDrawingFrame(frame
);
785 if (!expect_overlays_
) {
786 EXPECT_EQ(0U, frame
->overlay_list
.size());
790 ASSERT_EQ(2U, frame
->overlay_list
.size());
791 EXPECT_NE(0U, frame
->overlay_list
.back().resource_id
);
794 void set_expect_overlays(bool expect_overlays
) {
795 expect_overlays_
= expect_overlays
;
799 bool expect_overlays_
;
802 class FakeRendererClient
: public RendererClient
{
804 // RendererClient methods.
805 void SetFullRootLayerDamage() override
{}
808 class MockOverlayScheduler
{
810 MOCK_METHOD5(Schedule
,
811 void(int plane_z_order
,
812 gfx::OverlayTransform plane_transform
,
813 unsigned overlay_texture_id
,
814 const gfx::Rect
& display_bounds
,
815 const gfx::RectF
& uv_rect
));
818 class GLRendererWithOverlaysTest
: public testing::Test
{
820 GLRendererWithOverlaysTest() {
821 provider_
= TestContextProvider::Create();
822 output_surface_
.reset(new OverlayOutputSurface(provider_
));
823 CHECK(output_surface_
->BindToClient(&output_surface_client_
));
824 resource_provider_
= ResourceProvider::Create(
825 output_surface_
.get(), NULL
, NULL
, NULL
, 0, false, 1);
827 provider_
->support()->SetScheduleOverlayPlaneCallback(base::Bind(
828 &MockOverlayScheduler::Schedule
, base::Unretained(&scheduler_
)));
831 void Init(bool use_validator
) {
833 output_surface_
->InitWithSingleOverlayValidator();
836 make_scoped_ptr(new OverlayInfoRendererGL(&renderer_client_
,
838 output_surface_
.get(),
839 resource_provider_
.get()));
842 void SwapBuffers() { renderer_
->SwapBuffers(CompositorFrameMetadata()); }
844 RendererSettings settings_
;
845 FakeOutputSurfaceClient output_surface_client_
;
846 scoped_ptr
<OverlayOutputSurface
> output_surface_
;
847 FakeRendererClient renderer_client_
;
848 scoped_ptr
<ResourceProvider
> resource_provider_
;
849 scoped_ptr
<OverlayInfoRendererGL
> renderer_
;
850 scoped_refptr
<TestContextProvider
> provider_
;
851 MockOverlayScheduler scheduler_
;
854 TEST_F(GLRendererWithOverlaysTest
, OverlayQuadNotDrawn
) {
855 bool use_validator
= true;
857 renderer_
->set_expect_overlays(true);
858 gfx::Rect
viewport_rect(16, 16);
860 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
862 CreateFullscreenCandidateQuad(resource_provider_
.get(),
863 pass
->shared_quad_state_list
.back(),
866 CreateFullscreenCheckeredQuad(resource_provider_
.get(),
867 pass
->shared_quad_state_list
.back(),
869 CreateFullscreenCheckeredQuad(resource_provider_
.get(),
870 pass
->shared_quad_state_list
.back(),
873 RenderPassList pass_list
;
874 pass_list
.push_back(pass
.Pass());
876 // Candidate pass was taken out and extra skipped pass added,
877 // so only draw 2 quads.
878 EXPECT_CALL(*renderer_
, DoDrawQuad(_
, _
)).Times(2);
879 EXPECT_CALL(scheduler_
,
881 gfx::OVERLAY_TRANSFORM_NONE
,
884 BoundingRect(kUVTopLeft
, kUVBottomRight
))).Times(1);
885 renderer_
->DrawFrame(&pass_list
, 1.f
, viewport_rect
, viewport_rect
, false);
889 Mock::VerifyAndClearExpectations(renderer_
.get());
890 Mock::VerifyAndClearExpectations(&scheduler_
);
893 TEST_F(GLRendererWithOverlaysTest
, OccludedQuadDrawn
) {
894 bool use_validator
= true;
896 renderer_
->set_expect_overlays(false);
897 gfx::Rect
viewport_rect(16, 16);
899 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
901 CreateFullscreenCheckeredQuad(resource_provider_
.get(),
902 pass
->shared_quad_state_list
.back(),
904 CreateFullscreenCheckeredQuad(resource_provider_
.get(),
905 pass
->shared_quad_state_list
.back(),
908 CreateFullscreenCandidateQuad(resource_provider_
.get(),
909 pass
->shared_quad_state_list
.back(),
912 RenderPassList pass_list
;
913 pass_list
.push_back(pass
.Pass());
915 // 3 quads in the pass, all should draw.
916 EXPECT_CALL(*renderer_
, DoDrawQuad(_
, _
)).Times(3);
917 EXPECT_CALL(scheduler_
, Schedule(_
, _
, _
, _
, _
)).Times(0);
918 renderer_
->DrawFrame(&pass_list
, 1.f
, viewport_rect
, viewport_rect
, false);
922 Mock::VerifyAndClearExpectations(renderer_
.get());
923 Mock::VerifyAndClearExpectations(&scheduler_
);
926 TEST_F(GLRendererWithOverlaysTest
, NoValidatorNoOverlay
) {
927 bool use_validator
= false;
929 renderer_
->set_expect_overlays(false);
930 gfx::Rect
viewport_rect(16, 16);
932 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
934 CreateFullscreenCandidateQuad(resource_provider_
.get(),
935 pass
->shared_quad_state_list
.back(),
938 CreateFullscreenCheckeredQuad(resource_provider_
.get(),
939 pass
->shared_quad_state_list
.back(),
941 CreateFullscreenCheckeredQuad(resource_provider_
.get(),
942 pass
->shared_quad_state_list
.back(),
945 RenderPassList pass_list
;
946 pass_list
.push_back(pass
.Pass());
948 // Should see no overlays.
949 EXPECT_CALL(*renderer_
, DoDrawQuad(_
, _
)).Times(3);
950 EXPECT_CALL(scheduler_
, Schedule(_
, _
, _
, _
, _
)).Times(0);
951 renderer_
->DrawFrame(&pass_list
, 1.f
, viewport_rect
, viewport_rect
, false);
955 Mock::VerifyAndClearExpectations(renderer_
.get());
956 Mock::VerifyAndClearExpectations(&scheduler_
);
959 TEST_F(GLRendererWithOverlaysTest
, ResourcesExportedAndReturned
) {
960 bool use_validator
= true;
962 renderer_
->set_expect_overlays(true);
964 ResourceProvider::ResourceId resource1
=
965 CreateResource(resource_provider_
.get());
966 ResourceProvider::ResourceId resource2
=
967 CreateResource(resource_provider_
.get());
969 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
970 RenderPassList pass_list
;
971 pass_list
.push_back(pass
.Pass());
973 DirectRenderer::DrawingFrame frame1
;
974 frame1
.render_passes_in_draw_order
= &pass_list
;
975 frame1
.overlay_list
.resize(2);
976 OverlayCandidate
& overlay1
= frame1
.overlay_list
.back();
977 overlay1
.resource_id
= resource1
;
978 overlay1
.plane_z_order
= 1;
980 DirectRenderer::DrawingFrame frame2
;
981 frame2
.render_passes_in_draw_order
= &pass_list
;
982 frame2
.overlay_list
.resize(2);
983 OverlayCandidate
& overlay2
= frame2
.overlay_list
.back();
984 overlay2
.resource_id
= resource2
;
985 overlay2
.plane_z_order
= 1;
987 EXPECT_CALL(scheduler_
, Schedule(_
, _
, _
, _
, _
)).Times(1);
988 renderer_
->BeginDrawingFrame(&frame1
);
989 renderer_
->FinishDrawingFrame(&frame1
);
990 EXPECT_TRUE(resource_provider_
->InUseByConsumer(resource1
));
991 EXPECT_FALSE(resource_provider_
->InUseByConsumer(resource2
));
993 Mock::VerifyAndClearExpectations(&scheduler_
);
995 EXPECT_CALL(scheduler_
, Schedule(_
, _
, _
, _
, _
)).Times(1);
996 renderer_
->BeginDrawingFrame(&frame2
);
997 renderer_
->FinishDrawingFrame(&frame2
);
998 EXPECT_TRUE(resource_provider_
->InUseByConsumer(resource1
));
999 EXPECT_TRUE(resource_provider_
->InUseByConsumer(resource2
));
1001 EXPECT_FALSE(resource_provider_
->InUseByConsumer(resource1
));
1002 Mock::VerifyAndClearExpectations(&scheduler_
);
1004 EXPECT_CALL(scheduler_
, Schedule(_
, _
, _
, _
, _
)).Times(1);
1005 renderer_
->BeginDrawingFrame(&frame1
);
1006 renderer_
->FinishDrawingFrame(&frame1
);
1007 EXPECT_TRUE(resource_provider_
->InUseByConsumer(resource1
));
1008 EXPECT_TRUE(resource_provider_
->InUseByConsumer(resource2
));
1010 EXPECT_FALSE(resource_provider_
->InUseByConsumer(resource2
));
1011 Mock::VerifyAndClearExpectations(&scheduler_
);
1013 // No overlays, release the resource.
1014 EXPECT_CALL(scheduler_
, Schedule(_
, _
, _
, _
, _
)).Times(0);
1015 DirectRenderer::DrawingFrame frame3
;
1016 frame3
.render_passes_in_draw_order
= &pass_list
;
1017 renderer_
->set_expect_overlays(false);
1018 renderer_
->BeginDrawingFrame(&frame3
);
1019 renderer_
->FinishDrawingFrame(&frame3
);
1020 EXPECT_TRUE(resource_provider_
->InUseByConsumer(resource1
));
1021 EXPECT_FALSE(resource_provider_
->InUseByConsumer(resource2
));
1023 EXPECT_FALSE(resource_provider_
->InUseByConsumer(resource1
));
1024 Mock::VerifyAndClearExpectations(&scheduler_
);
1026 // Use the same buffer twice.
1027 renderer_
->set_expect_overlays(true);
1028 EXPECT_CALL(scheduler_
, Schedule(_
, _
, _
, _
, _
)).Times(1);
1029 renderer_
->BeginDrawingFrame(&frame1
);
1030 renderer_
->FinishDrawingFrame(&frame1
);
1031 EXPECT_TRUE(resource_provider_
->InUseByConsumer(resource1
));
1033 Mock::VerifyAndClearExpectations(&scheduler_
);
1035 EXPECT_CALL(scheduler_
, Schedule(_
, _
, _
, _
, _
)).Times(1);
1036 renderer_
->BeginDrawingFrame(&frame1
);
1037 renderer_
->FinishDrawingFrame(&frame1
);
1038 EXPECT_TRUE(resource_provider_
->InUseByConsumer(resource1
));
1040 EXPECT_TRUE(resource_provider_
->InUseByConsumer(resource1
));
1041 Mock::VerifyAndClearExpectations(&scheduler_
);
1043 EXPECT_CALL(scheduler_
, Schedule(_
, _
, _
, _
, _
)).Times(0);
1044 renderer_
->set_expect_overlays(false);
1045 renderer_
->BeginDrawingFrame(&frame3
);
1046 renderer_
->FinishDrawingFrame(&frame3
);
1047 EXPECT_TRUE(resource_provider_
->InUseByConsumer(resource1
));
1049 EXPECT_FALSE(resource_provider_
->InUseByConsumer(resource1
));
1050 Mock::VerifyAndClearExpectations(&scheduler_
);