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"
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
,
51 BlockingTaskRunner
* main_thread_task_runner
) {
54 class SingleOverlayValidator
: public OverlayCandidateValidator
{
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
);
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
{
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_
->GetOverlayCandidateValidator();
87 ASSERT_TRUE(candidates
!= NULL
);
88 strategies_
.push_back(scoped_ptr
<Strategy
>(
89 new OverlayStrategyType(candidates
, resource_provider_
)));
93 class DefaultOverlayProcessor
: public OverlayProcessor
{
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
{
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
);
121 OverlayCandidateValidator
* GetOverlayCandidateValidator() const override
{
122 return overlay_candidate_validator_
.get();
126 scoped_ptr
<OverlayCandidateValidator
> overlay_candidate_validator_
;
129 void OverlayOutputSurface::SwapBuffers(CompositorFrame
* frame
) {
130 client_
->DidSwapBuffers();
131 client_
->DidSwapBuffersComplete();
134 scoped_ptr
<RenderPass
> CreateRenderPass() {
135 RenderPassId
id(1, 0);
136 gfx::Rect
output_rect(0, 0, 256, 256);
137 bool has_transparent_background
= true;
139 scoped_ptr
<RenderPass
> pass
= RenderPass::Create();
144 has_transparent_background
);
146 SharedQuadState
* shared_state
= pass
->CreateAndAppendSharedQuadState();
147 shared_state
->opacity
= 1.f
;
151 ResourceProvider::ResourceId
CreateResource(
152 ResourceProvider
* resource_provider
) {
153 unsigned sync_point
= 0;
154 TextureMailbox mailbox
=
155 TextureMailbox(gpu::Mailbox::Generate(), GL_TEXTURE_2D
, sync_point
);
156 mailbox
.set_allow_overlay(true);
157 scoped_ptr
<SingleReleaseCallbackImpl
> release_callback
=
158 SingleReleaseCallbackImpl::Create(base::Bind(&MailboxReleased
));
160 return resource_provider
->CreateResourceFromTextureMailbox(
161 mailbox
, release_callback
.Pass());
164 SolidColorDrawQuad
* CreateSolidColorQuadAt(
165 const SharedQuadState
* shared_quad_state
,
167 RenderPass
* render_pass
,
168 const gfx::Rect
& rect
) {
169 SolidColorDrawQuad
* quad
=
170 render_pass
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
171 quad
->SetNew(shared_quad_state
, rect
, rect
, color
, false);
175 TextureDrawQuad
* CreateCandidateQuadAt(ResourceProvider
* resource_provider
,
176 const SharedQuadState
* shared_quad_state
,
177 RenderPass
* render_pass
,
178 const gfx::Rect
& rect
) {
179 ResourceProvider::ResourceId resource_id
= CreateResource(resource_provider
);
180 bool premultiplied_alpha
= false;
181 bool flipped
= false;
182 bool nearest_neighbor
= false;
183 float vertex_opacity
[4] = {1.0f
, 1.0f
, 1.0f
, 1.0f
};
185 TextureDrawQuad
* overlay_quad
=
186 render_pass
->CreateAndAppendDrawQuad
<TextureDrawQuad
>();
187 overlay_quad
->SetNew(shared_quad_state
,
203 StreamVideoDrawQuad
* CreateCandidateVideoQuadAt(
204 ResourceProvider
* resource_provider
,
205 const SharedQuadState
* shared_quad_state
,
206 RenderPass
* render_pass
,
207 const gfx::Rect
& rect
,
208 const gfx::Transform
& transform
) {
209 ResourceProvider::ResourceId resource_id
= CreateResource(resource_provider
);
211 StreamVideoDrawQuad
* overlay_quad
=
212 render_pass
->CreateAndAppendDrawQuad
<StreamVideoDrawQuad
>();
213 overlay_quad
->SetNew(shared_quad_state
, rect
, rect
, rect
, resource_id
,
219 TextureDrawQuad
* CreateFullscreenCandidateQuad(
220 ResourceProvider
* resource_provider
,
221 const SharedQuadState
* shared_quad_state
,
222 RenderPass
* render_pass
) {
223 return CreateCandidateQuadAt(
224 resource_provider
, shared_quad_state
, render_pass
, kOverlayRect
);
227 StreamVideoDrawQuad
* CreateFullscreenCandidateVideoQuad(
228 ResourceProvider
* resource_provider
,
229 const SharedQuadState
* shared_quad_state
,
230 RenderPass
* render_pass
,
231 const gfx::Transform
& transform
) {
232 return CreateCandidateVideoQuadAt(resource_provider
, shared_quad_state
,
233 render_pass
, kOverlayRect
, transform
);
236 void CreateCheckeredQuadAt(ResourceProvider
* resource_provider
,
237 const SharedQuadState
* shared_quad_state
,
238 RenderPass
* render_pass
,
239 const gfx::Rect
& rect
) {
240 CheckerboardDrawQuad
* checkerboard_quad
=
241 render_pass
->CreateAndAppendDrawQuad
<CheckerboardDrawQuad
>();
242 checkerboard_quad
->SetNew(shared_quad_state
, rect
, rect
, SkColor(), 1.f
);
245 void CreateFullscreenCheckeredQuad(ResourceProvider
* resource_provider
,
246 const SharedQuadState
* shared_quad_state
,
247 RenderPass
* render_pass
) {
248 CreateCheckeredQuadAt(
249 resource_provider
, shared_quad_state
, render_pass
, kOverlayRect
);
252 static void CompareRenderPassLists(const RenderPassList
& expected_list
,
253 const RenderPassList
& actual_list
) {
254 EXPECT_EQ(expected_list
.size(), actual_list
.size());
255 for (size_t i
= 0; i
< actual_list
.size(); ++i
) {
256 RenderPass
* expected
= expected_list
[i
];
257 RenderPass
* actual
= actual_list
[i
];
259 EXPECT_EQ(expected
->id
, actual
->id
);
260 EXPECT_EQ(expected
->output_rect
, actual
->output_rect
);
261 EXPECT_EQ(expected
->transform_to_root_target
,
262 actual
->transform_to_root_target
);
263 EXPECT_EQ(expected
->damage_rect
, actual
->damage_rect
);
264 EXPECT_EQ(expected
->has_transparent_background
,
265 actual
->has_transparent_background
);
267 EXPECT_EQ(expected
->shared_quad_state_list
.size(),
268 actual
->shared_quad_state_list
.size());
269 EXPECT_EQ(expected
->quad_list
.size(), actual
->quad_list
.size());
271 for (auto exp_iter
= expected
->quad_list
.cbegin(),
272 act_iter
= actual
->quad_list
.cbegin();
273 exp_iter
!= expected
->quad_list
.cend();
274 ++exp_iter
, ++act_iter
) {
275 EXPECT_EQ(exp_iter
->rect
.ToString(), act_iter
->rect
.ToString());
276 EXPECT_EQ(exp_iter
->shared_quad_state
->content_bounds
.ToString(),
277 act_iter
->shared_quad_state
->content_bounds
.ToString());
282 TEST(OverlayTest
, NoOverlaysByDefault
) {
283 scoped_refptr
<TestContextProvider
> provider
= TestContextProvider::Create();
284 OverlayOutputSurface
output_surface(provider
);
285 EXPECT_EQ(NULL
, output_surface
.GetOverlayCandidateValidator());
287 output_surface
.InitWithSingleOverlayValidator();
288 EXPECT_TRUE(output_surface
.GetOverlayCandidateValidator() != NULL
);
291 TEST(OverlayTest
, OverlaysProcessorHasStrategy
) {
292 scoped_refptr
<TestContextProvider
> provider
= TestContextProvider::Create();
293 OverlayOutputSurface
output_surface(provider
);
294 FakeOutputSurfaceClient client
;
295 EXPECT_TRUE(output_surface
.BindToClient(&client
));
296 output_surface
.InitWithSingleOverlayValidator();
297 EXPECT_TRUE(output_surface
.GetOverlayCandidateValidator() != NULL
);
299 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager(
300 new TestSharedBitmapManager());
301 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
302 &output_surface
, shared_bitmap_manager
.get(), NULL
, NULL
, 0, false, 1));
304 scoped_ptr
<DefaultOverlayProcessor
> overlay_processor(
305 new DefaultOverlayProcessor(&output_surface
, resource_provider
.get()));
306 overlay_processor
->Initialize();
307 EXPECT_GE(1U, overlay_processor
->GetStrategyCount());
310 template <typename OverlayStrategyType
>
311 class OverlayTest
: public testing::Test
{
313 void SetUp() override
{
314 provider_
= TestContextProvider::Create();
315 output_surface_
.reset(new OverlayOutputSurface(provider_
));
316 EXPECT_TRUE(output_surface_
->BindToClient(&client_
));
317 output_surface_
->InitWithSingleOverlayValidator();
318 EXPECT_TRUE(output_surface_
->GetOverlayCandidateValidator() != NULL
);
320 shared_bitmap_manager_
.reset(new TestSharedBitmapManager());
321 resource_provider_
= ResourceProvider::Create(output_surface_
.get(),
322 shared_bitmap_manager_
.get(),
329 overlay_processor_
.reset(new SingleOverlayProcessor
<OverlayStrategyType
>(
330 output_surface_
.get(), resource_provider_
.get()));
331 overlay_processor_
->Initialize();
334 scoped_refptr
<TestContextProvider
> provider_
;
335 scoped_ptr
<OverlayOutputSurface
> output_surface_
;
336 FakeOutputSurfaceClient client_
;
337 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager_
;
338 scoped_ptr
<ResourceProvider
> resource_provider_
;
339 scoped_ptr
<SingleOverlayProcessor
<OverlayStrategyType
>> overlay_processor_
;
342 typedef OverlayTest
<OverlayStrategySingleOnTop
> SingleOverlayOnTopTest
;
343 typedef OverlayTest
<OverlayStrategyUnderlay
> UnderlayTest
;
345 TEST_F(SingleOverlayOnTopTest
, SuccessfullOverlay
) {
346 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
347 TextureDrawQuad
* original_quad
=
348 CreateFullscreenCandidateQuad(resource_provider_
.get(),
349 pass
->shared_quad_state_list
.back(),
351 unsigned original_resource_id
= original_quad
->resource_id
;
353 // Add something behind it.
354 CreateFullscreenCheckeredQuad(resource_provider_
.get(),
355 pass
->shared_quad_state_list
.back(),
357 CreateFullscreenCheckeredQuad(resource_provider_
.get(),
358 pass
->shared_quad_state_list
.back(),
361 RenderPassList pass_list
;
362 pass_list
.push_back(pass
.Pass());
364 // Check for potential candidates.
365 OverlayCandidateList candidate_list
;
366 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
368 ASSERT_EQ(1U, pass_list
.size());
369 ASSERT_EQ(2U, candidate_list
.size());
371 RenderPass
* main_pass
= pass_list
.back();
372 // Check that the quad is gone.
373 EXPECT_EQ(2U, main_pass
->quad_list
.size());
374 const QuadList
& quad_list
= main_pass
->quad_list
;
375 for (QuadList::ConstBackToFrontIterator it
= quad_list
.BackToFrontBegin();
376 it
!= quad_list
.BackToFrontEnd();
378 EXPECT_NE(DrawQuad::TEXTURE_CONTENT
, it
->material
);
381 // Check that the right resource id got extracted.
382 EXPECT_EQ(original_resource_id
, candidate_list
.back().resource_id
);
385 TEST_F(SingleOverlayOnTopTest
, NoCandidates
) {
386 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
387 CreateFullscreenCheckeredQuad(resource_provider_
.get(),
388 pass
->shared_quad_state_list
.back(),
390 CreateFullscreenCheckeredQuad(resource_provider_
.get(),
391 pass
->shared_quad_state_list
.back(),
394 RenderPassList pass_list
;
395 pass_list
.push_back(pass
.Pass());
397 RenderPassList original_pass_list
;
398 RenderPass::CopyAll(pass_list
, &original_pass_list
);
400 OverlayCandidateList candidate_list
;
401 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
402 EXPECT_EQ(0U, candidate_list
.size());
403 // There should be nothing new here.
404 CompareRenderPassLists(pass_list
, original_pass_list
);
407 TEST_F(SingleOverlayOnTopTest
, OccludedCandidates
) {
408 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
409 CreateFullscreenCheckeredQuad(resource_provider_
.get(),
410 pass
->shared_quad_state_list
.back(),
412 CreateFullscreenCheckeredQuad(resource_provider_
.get(),
413 pass
->shared_quad_state_list
.back(),
416 CreateFullscreenCandidateQuad(resource_provider_
.get(),
417 pass
->shared_quad_state_list
.back(),
420 RenderPassList pass_list
;
421 pass_list
.push_back(pass
.Pass());
423 RenderPassList original_pass_list
;
424 RenderPass::CopyAll(pass_list
, &original_pass_list
);
426 OverlayCandidateList candidate_list
;
427 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
428 EXPECT_EQ(0U, candidate_list
.size());
429 // There should be nothing new here.
430 CompareRenderPassLists(pass_list
, original_pass_list
);
433 // Test with multiple render passes.
434 TEST_F(SingleOverlayOnTopTest
, MultipleRenderPasses
) {
435 RenderPassList pass_list
;
436 pass_list
.push_back(CreateRenderPass());
438 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
439 CreateFullscreenCandidateQuad(resource_provider_
.get(),
440 pass
->shared_quad_state_list
.back(),
443 // Add something behind it.
444 CreateFullscreenCheckeredQuad(resource_provider_
.get(),
445 pass
->shared_quad_state_list
.back(),
447 CreateFullscreenCheckeredQuad(resource_provider_
.get(),
448 pass
->shared_quad_state_list
.back(),
451 pass_list
.push_back(pass
.Pass());
453 RenderPassList original_pass_list
;
454 RenderPass::CopyAll(pass_list
, &original_pass_list
);
456 // Check for potential candidates.
457 OverlayCandidateList candidate_list
;
458 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
459 EXPECT_EQ(2U, candidate_list
.size());
461 // This should be the same.
462 ASSERT_EQ(2U, pass_list
.size());
465 TEST_F(SingleOverlayOnTopTest
, RejectPremultipliedAlpha
) {
466 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
467 TextureDrawQuad
* quad
=
468 CreateFullscreenCandidateQuad(resource_provider_
.get(),
469 pass
->shared_quad_state_list
.back(),
471 quad
->premultiplied_alpha
= true;
473 RenderPassList pass_list
;
474 pass_list
.push_back(pass
.Pass());
475 OverlayCandidateList candidate_list
;
476 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
477 EXPECT_EQ(1U, pass_list
.size());
478 EXPECT_EQ(0U, candidate_list
.size());
481 TEST_F(SingleOverlayOnTopTest
, RejectBlending
) {
482 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
483 TextureDrawQuad
* quad
=
484 CreateFullscreenCandidateQuad(resource_provider_
.get(),
485 pass
->shared_quad_state_list
.back(),
487 quad
->needs_blending
= true;
489 RenderPassList pass_list
;
490 pass_list
.push_back(pass
.Pass());
491 OverlayCandidateList candidate_list
;
492 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
493 ASSERT_EQ(1U, pass_list
.size());
494 EXPECT_EQ(0U, candidate_list
.size());
497 TEST_F(SingleOverlayOnTopTest
, RejectBackgroundColor
) {
498 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
499 TextureDrawQuad
* quad
=
500 CreateFullscreenCandidateQuad(resource_provider_
.get(),
501 pass
->shared_quad_state_list
.back(),
503 quad
->background_color
= SK_ColorBLACK
;
505 RenderPassList pass_list
;
506 pass_list
.push_back(pass
.Pass());
507 OverlayCandidateList candidate_list
;
508 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
509 ASSERT_EQ(1U, pass_list
.size());
510 EXPECT_EQ(0U, candidate_list
.size());
513 TEST_F(SingleOverlayOnTopTest
, RejectBlendMode
) {
514 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
515 CreateFullscreenCandidateQuad(resource_provider_
.get(),
516 pass
->shared_quad_state_list
.back(),
518 pass
->shared_quad_state_list
.back()->blend_mode
= SkXfermode::kScreen_Mode
;
520 RenderPassList pass_list
;
521 pass_list
.push_back(pass
.Pass());
522 OverlayCandidateList candidate_list
;
523 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
524 ASSERT_EQ(1U, pass_list
.size());
525 EXPECT_EQ(0U, candidate_list
.size());
528 TEST_F(SingleOverlayOnTopTest
, RejectOpacity
) {
529 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
530 CreateFullscreenCandidateQuad(resource_provider_
.get(),
531 pass
->shared_quad_state_list
.back(),
533 pass
->shared_quad_state_list
.back()->opacity
= 0.5f
;
535 RenderPassList pass_list
;
536 pass_list
.push_back(pass
.Pass());
537 OverlayCandidateList candidate_list
;
538 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
539 ASSERT_EQ(1U, pass_list
.size());
540 EXPECT_EQ(0U, candidate_list
.size());
543 TEST_F(SingleOverlayOnTopTest
, RejectNonScaleTransform
) {
544 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
545 CreateFullscreenCandidateQuad(resource_provider_
.get(),
546 pass
->shared_quad_state_list
.back(),
548 pass
->shared_quad_state_list
.back()
549 ->content_to_target_transform
.RotateAboutXAxis(45.f
);
551 RenderPassList pass_list
;
552 pass_list
.push_back(pass
.Pass());
553 OverlayCandidateList candidate_list
;
554 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
555 ASSERT_EQ(1U, pass_list
.size());
556 EXPECT_EQ(0U, candidate_list
.size());
559 TEST_F(SingleOverlayOnTopTest
, RejectNegativeScaleTransform
) {
560 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
561 CreateFullscreenCandidateQuad(resource_provider_
.get(),
562 pass
->shared_quad_state_list
.back(),
564 pass
->shared_quad_state_list
.back()->content_to_target_transform
.Scale(2.0f
,
567 RenderPassList pass_list
;
568 pass_list
.push_back(pass
.Pass());
569 OverlayCandidateList candidate_list
;
570 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
571 ASSERT_EQ(1U, pass_list
.size());
572 EXPECT_EQ(0U, candidate_list
.size());
575 TEST_F(SingleOverlayOnTopTest
, AllowPositiveScaleTransform
) {
576 gfx::Rect rect
= kOverlayRect
;
577 rect
.set_width(rect
.width() / 2);
578 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
579 CreateCandidateQuadAt(resource_provider_
.get(),
580 pass
->shared_quad_state_list
.back(), pass
.get(), rect
);
581 pass
->shared_quad_state_list
.back()->content_to_target_transform
.Scale(2.0f
,
584 RenderPassList pass_list
;
585 pass_list
.push_back(pass
.Pass());
586 OverlayCandidateList candidate_list
;
587 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
588 ASSERT_EQ(1U, pass_list
.size());
589 EXPECT_EQ(2U, candidate_list
.size());
592 TEST_F(SingleOverlayOnTopTest
, AllowNotTopIfNotOccluded
) {
593 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
594 CreateCheckeredQuadAt(resource_provider_
.get(),
595 pass
->shared_quad_state_list
.back(),
597 kOverlayTopLeftRect
);
598 CreateCandidateQuadAt(resource_provider_
.get(),
599 pass
->shared_quad_state_list
.back(),
601 kOverlayBottomRightRect
);
603 RenderPassList pass_list
;
604 pass_list
.push_back(pass
.Pass());
606 RenderPassList original_pass_list
;
607 RenderPass::CopyAll(pass_list
, &original_pass_list
);
609 OverlayCandidateList candidate_list
;
610 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
611 EXPECT_EQ(1U, pass_list
.size());
612 EXPECT_EQ(2U, candidate_list
.size());
615 TEST_F(SingleOverlayOnTopTest
, AllowTransparentOnTop
) {
616 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
617 SharedQuadState
* shared_state
= pass
->CreateAndAppendSharedQuadState();
618 shared_state
->opacity
= 0.f
;
619 CreateSolidColorQuadAt(shared_state
, SK_ColorBLACK
, pass
.get(),
620 kOverlayBottomRightRect
);
621 shared_state
= pass
->CreateAndAppendSharedQuadState();
622 shared_state
->opacity
= 1.f
;
623 CreateCandidateQuadAt(resource_provider_
.get(), shared_state
, pass
.get(),
624 kOverlayBottomRightRect
);
626 RenderPassList pass_list
;
627 pass_list
.push_back(pass
.Pass());
629 RenderPassList original_pass_list
;
630 RenderPass::CopyAll(pass_list
, &original_pass_list
);
632 OverlayCandidateList candidate_list
;
633 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
634 EXPECT_EQ(1U, pass_list
.size());
635 EXPECT_EQ(2U, candidate_list
.size());
638 TEST_F(SingleOverlayOnTopTest
, AllowTransparentColorOnTop
) {
639 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
640 CreateSolidColorQuadAt(pass
->shared_quad_state_list
.back(),
641 SK_ColorTRANSPARENT
, pass
.get(),
642 kOverlayBottomRightRect
);
643 CreateCandidateQuadAt(resource_provider_
.get(),
644 pass
->shared_quad_state_list
.back(), pass
.get(),
645 kOverlayBottomRightRect
);
647 RenderPassList pass_list
;
648 pass_list
.push_back(pass
.Pass());
650 RenderPassList original_pass_list
;
651 RenderPass::CopyAll(pass_list
, &original_pass_list
);
653 OverlayCandidateList candidate_list
;
654 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
655 EXPECT_EQ(1U, pass_list
.size());
656 EXPECT_EQ(2U, candidate_list
.size());
659 TEST_F(SingleOverlayOnTopTest
, RejectOpaqueColorOnTop
) {
660 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
661 SharedQuadState
* shared_state
= pass
->CreateAndAppendSharedQuadState();
662 shared_state
->opacity
= 0.5f
;
663 CreateSolidColorQuadAt(shared_state
, SK_ColorBLACK
, pass
.get(),
664 kOverlayBottomRightRect
);
665 shared_state
= pass
->CreateAndAppendSharedQuadState();
666 shared_state
->opacity
= 1.f
;
667 CreateCandidateQuadAt(resource_provider_
.get(), shared_state
, pass
.get(),
668 kOverlayBottomRightRect
);
670 RenderPassList pass_list
;
671 pass_list
.push_back(pass
.Pass());
673 RenderPassList original_pass_list
;
674 RenderPass::CopyAll(pass_list
, &original_pass_list
);
676 OverlayCandidateList candidate_list
;
677 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
678 EXPECT_EQ(1U, pass_list
.size());
679 EXPECT_EQ(0U, candidate_list
.size());
682 TEST_F(SingleOverlayOnTopTest
, RejectTransparentColorOnTopWithoutBlending
) {
683 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
684 SharedQuadState
* shared_state
= pass
->CreateAndAppendSharedQuadState();
685 CreateSolidColorQuadAt(shared_state
, SK_ColorTRANSPARENT
, pass
.get(),
686 kOverlayBottomRightRect
)->opaque_rect
=
687 kOverlayBottomRightRect
;
688 CreateCandidateQuadAt(resource_provider_
.get(), shared_state
, pass
.get(),
689 kOverlayBottomRightRect
);
691 RenderPassList pass_list
;
692 pass_list
.push_back(pass
.Pass());
694 RenderPassList original_pass_list
;
695 RenderPass::CopyAll(pass_list
, &original_pass_list
);
697 OverlayCandidateList candidate_list
;
698 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
699 EXPECT_EQ(1U, pass_list
.size());
700 EXPECT_EQ(0U, candidate_list
.size());
703 TEST_F(SingleOverlayOnTopTest
, RejectVideoSwapTransform
) {
704 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
705 CreateFullscreenCandidateVideoQuad(resource_provider_
.get(),
706 pass
->shared_quad_state_list
.back(),
707 pass
.get(), kSwapTransform
);
709 RenderPassList pass_list
;
710 pass_list
.push_back(pass
.Pass());
711 OverlayCandidateList candidate_list
;
712 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
713 ASSERT_EQ(1U, pass_list
.size());
714 EXPECT_EQ(0U, candidate_list
.size());
717 TEST_F(SingleOverlayOnTopTest
, AllowVideoXMirrorTransform
) {
718 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
719 CreateFullscreenCandidateVideoQuad(resource_provider_
.get(),
720 pass
->shared_quad_state_list
.back(),
721 pass
.get(), kXMirrorTransform
);
723 RenderPassList pass_list
;
724 pass_list
.push_back(pass
.Pass());
725 OverlayCandidateList candidate_list
;
726 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
727 ASSERT_EQ(1U, pass_list
.size());
728 EXPECT_EQ(2U, candidate_list
.size());
731 TEST_F(SingleOverlayOnTopTest
, AllowVideoBothMirrorTransform
) {
732 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
733 CreateFullscreenCandidateVideoQuad(resource_provider_
.get(),
734 pass
->shared_quad_state_list
.back(),
735 pass
.get(), kBothMirrorTransform
);
737 RenderPassList pass_list
;
738 pass_list
.push_back(pass
.Pass());
739 OverlayCandidateList candidate_list
;
740 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
741 ASSERT_EQ(1U, pass_list
.size());
742 EXPECT_EQ(2U, candidate_list
.size());
745 TEST_F(SingleOverlayOnTopTest
, AllowVideoNormalTransform
) {
746 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
747 CreateFullscreenCandidateVideoQuad(resource_provider_
.get(),
748 pass
->shared_quad_state_list
.back(),
749 pass
.get(), kNormalTransform
);
751 RenderPassList pass_list
;
752 pass_list
.push_back(pass
.Pass());
753 OverlayCandidateList candidate_list
;
754 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
755 ASSERT_EQ(1U, pass_list
.size());
756 EXPECT_EQ(2U, candidate_list
.size());
759 TEST_F(SingleOverlayOnTopTest
, AllowVideoYMirrorTransform
) {
760 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
761 CreateFullscreenCandidateVideoQuad(resource_provider_
.get(),
762 pass
->shared_quad_state_list
.back(),
763 pass
.get(), kYMirrorTransform
);
765 RenderPassList pass_list
;
766 pass_list
.push_back(pass
.Pass());
767 OverlayCandidateList candidate_list
;
768 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
769 ASSERT_EQ(1U, pass_list
.size());
770 EXPECT_EQ(2U, candidate_list
.size());
773 TEST_F(UnderlayTest
, OverlayLayerUnderMainLayer
) {
774 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
775 CreateFullscreenCheckeredQuad(resource_provider_
.get(),
776 pass
->shared_quad_state_list
.back(),
778 CreateCandidateQuadAt(resource_provider_
.get(),
779 pass
->shared_quad_state_list
.back(), pass
.get(),
780 kOverlayBottomRightRect
);
782 RenderPassList pass_list
;
783 pass_list
.push_back(pass
.Pass());
785 OverlayCandidateList candidate_list
;
786 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
787 EXPECT_EQ(1U, pass_list
.size());
788 ASSERT_EQ(2U, candidate_list
.size());
789 EXPECT_EQ(0, candidate_list
[0].plane_z_order
);
790 EXPECT_EQ(-1, candidate_list
[1].plane_z_order
);
791 EXPECT_EQ(2U, pass_list
[0]->quad_list
.size());
792 // The overlay quad should have changed to a SOLID_COLOR quad.
793 EXPECT_EQ(pass_list
[0]->quad_list
.back()->material
, DrawQuad::SOLID_COLOR
);
796 TEST_F(UnderlayTest
, AllowOnTop
) {
797 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
798 CreateFullscreenCandidateQuad(resource_provider_
.get(),
799 pass
->shared_quad_state_list
.back(),
801 pass
->CreateAndAppendSharedQuadState()->opacity
= 0.5f
;
802 CreateFullscreenCheckeredQuad(resource_provider_
.get(),
803 pass
->shared_quad_state_list
.back(),
806 RenderPassList pass_list
;
807 pass_list
.push_back(pass
.Pass());
809 OverlayCandidateList candidate_list
;
810 overlay_processor_
->ProcessForOverlays(&pass_list
, &candidate_list
);
811 EXPECT_EQ(1U, pass_list
.size());
812 ASSERT_EQ(2U, candidate_list
.size());
813 EXPECT_EQ(0, candidate_list
[0].plane_z_order
);
814 EXPECT_EQ(-1, candidate_list
[1].plane_z_order
);
815 // The overlay quad should have changed to a SOLID_COLOR quad.
816 EXPECT_EQ(pass_list
[0]->quad_list
.front()->material
, DrawQuad::SOLID_COLOR
);
819 class OverlayInfoRendererGL
: public GLRenderer
{
821 OverlayInfoRendererGL(RendererClient
* client
,
822 const RendererSettings
* settings
,
823 OutputSurface
* output_surface
,
824 ResourceProvider
* resource_provider
)
831 expect_overlays_(false) {}
833 MOCK_METHOD3(DoDrawQuad
,
834 void(DrawingFrame
* frame
,
835 const DrawQuad
* quad
,
836 const gfx::QuadF
* draw_region
));
838 using GLRenderer::BeginDrawingFrame
;
840 void FinishDrawingFrame(DrawingFrame
* frame
) override
{
841 GLRenderer::FinishDrawingFrame(frame
);
843 if (!expect_overlays_
) {
844 EXPECT_EQ(0U, frame
->overlay_list
.size());
848 ASSERT_EQ(2U, frame
->overlay_list
.size());
849 EXPECT_NE(0U, frame
->overlay_list
.back().resource_id
);
852 void set_expect_overlays(bool expect_overlays
) {
853 expect_overlays_
= expect_overlays
;
857 bool expect_overlays_
;
860 class FakeRendererClient
: public RendererClient
{
862 // RendererClient methods.
863 void SetFullRootLayerDamage() override
{}
866 class MockOverlayScheduler
{
868 MOCK_METHOD5(Schedule
,
869 void(int plane_z_order
,
870 gfx::OverlayTransform plane_transform
,
871 unsigned overlay_texture_id
,
872 const gfx::Rect
& display_bounds
,
873 const gfx::RectF
& uv_rect
));
876 class GLRendererWithOverlaysTest
: public testing::Test
{
878 GLRendererWithOverlaysTest() {
879 provider_
= TestContextProvider::Create();
880 output_surface_
.reset(new OverlayOutputSurface(provider_
));
881 CHECK(output_surface_
->BindToClient(&output_surface_client_
));
882 resource_provider_
= ResourceProvider::Create(
883 output_surface_
.get(), NULL
, NULL
, NULL
, 0, false, 1);
885 provider_
->support()->SetScheduleOverlayPlaneCallback(base::Bind(
886 &MockOverlayScheduler::Schedule
, base::Unretained(&scheduler_
)));
889 void Init(bool use_validator
) {
891 output_surface_
->InitWithSingleOverlayValidator();
894 make_scoped_ptr(new OverlayInfoRendererGL(&renderer_client_
,
896 output_surface_
.get(),
897 resource_provider_
.get()));
900 void SwapBuffers() { renderer_
->SwapBuffers(CompositorFrameMetadata()); }
902 RendererSettings settings_
;
903 FakeOutputSurfaceClient output_surface_client_
;
904 scoped_ptr
<OverlayOutputSurface
> output_surface_
;
905 FakeRendererClient renderer_client_
;
906 scoped_ptr
<ResourceProvider
> resource_provider_
;
907 scoped_ptr
<OverlayInfoRendererGL
> renderer_
;
908 scoped_refptr
<TestContextProvider
> provider_
;
909 MockOverlayScheduler scheduler_
;
912 TEST_F(GLRendererWithOverlaysTest
, OverlayQuadNotDrawn
) {
913 bool use_validator
= true;
915 renderer_
->set_expect_overlays(true);
916 gfx::Rect
viewport_rect(16, 16);
918 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
920 CreateFullscreenCandidateQuad(resource_provider_
.get(),
921 pass
->shared_quad_state_list
.back(),
924 CreateFullscreenCheckeredQuad(resource_provider_
.get(),
925 pass
->shared_quad_state_list
.back(),
927 CreateFullscreenCheckeredQuad(resource_provider_
.get(),
928 pass
->shared_quad_state_list
.back(),
931 RenderPassList pass_list
;
932 pass_list
.push_back(pass
.Pass());
934 // Candidate pass was taken out and extra skipped pass added,
935 // so only draw 2 quads.
936 EXPECT_CALL(*renderer_
, DoDrawQuad(_
, _
, _
)).Times(2);
937 EXPECT_CALL(scheduler_
,
939 gfx::OVERLAY_TRANSFORM_NONE
,
942 BoundingRect(kUVTopLeft
, kUVBottomRight
))).Times(1);
943 renderer_
->DrawFrame(&pass_list
, 1.f
, viewport_rect
, viewport_rect
, false);
947 Mock::VerifyAndClearExpectations(renderer_
.get());
948 Mock::VerifyAndClearExpectations(&scheduler_
);
951 TEST_F(GLRendererWithOverlaysTest
, OccludedQuadDrawn
) {
952 bool use_validator
= true;
954 renderer_
->set_expect_overlays(false);
955 gfx::Rect
viewport_rect(16, 16);
957 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
959 CreateFullscreenCheckeredQuad(resource_provider_
.get(),
960 pass
->shared_quad_state_list
.back(),
962 CreateFullscreenCheckeredQuad(resource_provider_
.get(),
963 pass
->shared_quad_state_list
.back(),
966 CreateFullscreenCandidateQuad(resource_provider_
.get(),
967 pass
->shared_quad_state_list
.back(),
970 RenderPassList pass_list
;
971 pass_list
.push_back(pass
.Pass());
973 // 3 quads in the pass, all should draw.
974 EXPECT_CALL(*renderer_
, DoDrawQuad(_
, _
, _
)).Times(3);
975 EXPECT_CALL(scheduler_
, Schedule(_
, _
, _
, _
, _
)).Times(0);
976 renderer_
->DrawFrame(&pass_list
, 1.f
, viewport_rect
, viewport_rect
, false);
980 Mock::VerifyAndClearExpectations(renderer_
.get());
981 Mock::VerifyAndClearExpectations(&scheduler_
);
984 TEST_F(GLRendererWithOverlaysTest
, NoValidatorNoOverlay
) {
985 bool use_validator
= false;
987 renderer_
->set_expect_overlays(false);
988 gfx::Rect
viewport_rect(16, 16);
990 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
992 CreateFullscreenCandidateQuad(resource_provider_
.get(),
993 pass
->shared_quad_state_list
.back(),
996 CreateFullscreenCheckeredQuad(resource_provider_
.get(),
997 pass
->shared_quad_state_list
.back(),
999 CreateFullscreenCheckeredQuad(resource_provider_
.get(),
1000 pass
->shared_quad_state_list
.back(),
1003 RenderPassList pass_list
;
1004 pass_list
.push_back(pass
.Pass());
1006 // Should see no overlays.
1007 EXPECT_CALL(*renderer_
, DoDrawQuad(_
, _
, _
)).Times(3);
1008 EXPECT_CALL(scheduler_
, Schedule(_
, _
, _
, _
, _
)).Times(0);
1009 renderer_
->DrawFrame(&pass_list
, 1.f
, viewport_rect
, viewport_rect
, false);
1013 Mock::VerifyAndClearExpectations(renderer_
.get());
1014 Mock::VerifyAndClearExpectations(&scheduler_
);
1017 TEST_F(GLRendererWithOverlaysTest
, ResourcesExportedAndReturned
) {
1018 bool use_validator
= true;
1019 Init(use_validator
);
1020 renderer_
->set_expect_overlays(true);
1022 ResourceProvider::ResourceId resource1
=
1023 CreateResource(resource_provider_
.get());
1024 ResourceProvider::ResourceId resource2
=
1025 CreateResource(resource_provider_
.get());
1027 scoped_ptr
<RenderPass
> pass
= CreateRenderPass();
1028 RenderPassList pass_list
;
1029 pass_list
.push_back(pass
.Pass());
1031 DirectRenderer::DrawingFrame frame1
;
1032 frame1
.render_passes_in_draw_order
= &pass_list
;
1033 frame1
.overlay_list
.resize(2);
1034 OverlayCandidate
& overlay1
= frame1
.overlay_list
.back();
1035 overlay1
.resource_id
= resource1
;
1036 overlay1
.plane_z_order
= 1;
1038 DirectRenderer::DrawingFrame frame2
;
1039 frame2
.render_passes_in_draw_order
= &pass_list
;
1040 frame2
.overlay_list
.resize(2);
1041 OverlayCandidate
& overlay2
= frame2
.overlay_list
.back();
1042 overlay2
.resource_id
= resource2
;
1043 overlay2
.plane_z_order
= 1;
1045 EXPECT_CALL(scheduler_
, Schedule(_
, _
, _
, _
, _
)).Times(1);
1046 renderer_
->BeginDrawingFrame(&frame1
);
1047 renderer_
->FinishDrawingFrame(&frame1
);
1048 EXPECT_TRUE(resource_provider_
->InUseByConsumer(resource1
));
1049 EXPECT_FALSE(resource_provider_
->InUseByConsumer(resource2
));
1051 Mock::VerifyAndClearExpectations(&scheduler_
);
1053 EXPECT_CALL(scheduler_
, Schedule(_
, _
, _
, _
, _
)).Times(1);
1054 renderer_
->BeginDrawingFrame(&frame2
);
1055 renderer_
->FinishDrawingFrame(&frame2
);
1056 EXPECT_TRUE(resource_provider_
->InUseByConsumer(resource1
));
1057 EXPECT_TRUE(resource_provider_
->InUseByConsumer(resource2
));
1059 EXPECT_FALSE(resource_provider_
->InUseByConsumer(resource1
));
1060 Mock::VerifyAndClearExpectations(&scheduler_
);
1062 EXPECT_CALL(scheduler_
, Schedule(_
, _
, _
, _
, _
)).Times(1);
1063 renderer_
->BeginDrawingFrame(&frame1
);
1064 renderer_
->FinishDrawingFrame(&frame1
);
1065 EXPECT_TRUE(resource_provider_
->InUseByConsumer(resource1
));
1066 EXPECT_TRUE(resource_provider_
->InUseByConsumer(resource2
));
1068 EXPECT_FALSE(resource_provider_
->InUseByConsumer(resource2
));
1069 Mock::VerifyAndClearExpectations(&scheduler_
);
1071 // No overlays, release the resource.
1072 EXPECT_CALL(scheduler_
, Schedule(_
, _
, _
, _
, _
)).Times(0);
1073 DirectRenderer::DrawingFrame frame3
;
1074 frame3
.render_passes_in_draw_order
= &pass_list
;
1075 renderer_
->set_expect_overlays(false);
1076 renderer_
->BeginDrawingFrame(&frame3
);
1077 renderer_
->FinishDrawingFrame(&frame3
);
1078 EXPECT_TRUE(resource_provider_
->InUseByConsumer(resource1
));
1079 EXPECT_FALSE(resource_provider_
->InUseByConsumer(resource2
));
1081 EXPECT_FALSE(resource_provider_
->InUseByConsumer(resource1
));
1082 Mock::VerifyAndClearExpectations(&scheduler_
);
1084 // Use the same buffer twice.
1085 renderer_
->set_expect_overlays(true);
1086 EXPECT_CALL(scheduler_
, Schedule(_
, _
, _
, _
, _
)).Times(1);
1087 renderer_
->BeginDrawingFrame(&frame1
);
1088 renderer_
->FinishDrawingFrame(&frame1
);
1089 EXPECT_TRUE(resource_provider_
->InUseByConsumer(resource1
));
1091 Mock::VerifyAndClearExpectations(&scheduler_
);
1093 EXPECT_CALL(scheduler_
, Schedule(_
, _
, _
, _
, _
)).Times(1);
1094 renderer_
->BeginDrawingFrame(&frame1
);
1095 renderer_
->FinishDrawingFrame(&frame1
);
1096 EXPECT_TRUE(resource_provider_
->InUseByConsumer(resource1
));
1098 EXPECT_TRUE(resource_provider_
->InUseByConsumer(resource1
));
1099 Mock::VerifyAndClearExpectations(&scheduler_
);
1101 EXPECT_CALL(scheduler_
, Schedule(_
, _
, _
, _
, _
)).Times(0);
1102 renderer_
->set_expect_overlays(false);
1103 renderer_
->BeginDrawingFrame(&frame3
);
1104 renderer_
->FinishDrawingFrame(&frame3
);
1105 EXPECT_TRUE(resource_provider_
->InUseByConsumer(resource1
));
1107 EXPECT_FALSE(resource_provider_
->InUseByConsumer(resource1
));
1108 Mock::VerifyAndClearExpectations(&scheduler_
);