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_
->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
{
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
);
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();
137 has_transparent_background
);
139 SharedQuadState
* shared_state
= pass
->CreateAndAppendSharedQuadState();
140 shared_state
->opacity
= 1.f
;
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
,
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);
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
,
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
,
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
{
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(),
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(),
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(),
350 CreateFullscreenCheckeredQuad(resource_provider_
.get(),
351 pass
->shared_quad_state_list
.back(),
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();
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(),
383 CreateFullscreenCheckeredQuad(resource_provider_
.get(),
384 pass
->shared_quad_state_list
.back(),
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(),
405 CreateFullscreenCheckeredQuad(resource_provider_
.get(),
406 pass
->shared_quad_state_list
.back(),
409 CreateFullscreenCandidateQuad(resource_provider_
.get(),
410 pass
->shared_quad_state_list
.back(),
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(),
436 // Add something behind it.
437 CreateFullscreenCheckeredQuad(resource_provider_
.get(),
438 pass
->shared_quad_state_list
.back(),
440 CreateFullscreenCheckeredQuad(resource_provider_
.get(),
441 pass
->shared_quad_state_list
.back(),
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(),
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(),
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(),
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(),
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(),
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(),
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(),
557 pass
->shared_quad_state_list
.back()->content_to_target_transform
.Scale(2.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
,
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(),
590 kOverlayTopLeftRect
);
591 CreateCandidateQuadAt(resource_provider_
.get(),
592 pass
->shared_quad_state_list
.back(),
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(),
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(),
794 pass
->CreateAndAppendSharedQuadState()->opacity
= 0.5f
;
795 CreateFullscreenCheckeredQuad(resource_provider_
.get(),
796 pass
->shared_quad_state_list
.back(),
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
{
814 OverlayInfoRendererGL(RendererClient
* client
,
815 const RendererSettings
* settings
,
816 OutputSurface
* output_surface
,
817 ResourceProvider
* resource_provider
)
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());
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
;
850 bool expect_overlays_
;
853 class FakeRendererClient
: public RendererClient
{
855 // RendererClient methods.
856 void SetFullRootLayerDamage() override
{}
859 class MockOverlayScheduler
{
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
{
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
) {
884 output_surface_
->InitWithSingleOverlayValidator();
887 make_scoped_ptr(new OverlayInfoRendererGL(&renderer_client_
,
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;
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(),
917 CreateFullscreenCheckeredQuad(resource_provider_
.get(),
918 pass
->shared_quad_state_list
.back(),
920 CreateFullscreenCheckeredQuad(resource_provider_
.get(),
921 pass
->shared_quad_state_list
.back(),
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_
,
932 gfx::OVERLAY_TRANSFORM_NONE
,
935 BoundingRect(kUVTopLeft
, kUVBottomRight
))).Times(1);
936 renderer_
->DrawFrame(&pass_list
, 1.f
, viewport_rect
, viewport_rect
, false);
940 Mock::VerifyAndClearExpectations(renderer_
.get());
941 Mock::VerifyAndClearExpectations(&scheduler_
);
944 TEST_F(GLRendererWithOverlaysTest
, OccludedQuadDrawn
) {
945 bool use_validator
= true;
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(),
955 CreateFullscreenCheckeredQuad(resource_provider_
.get(),
956 pass
->shared_quad_state_list
.back(),
959 CreateFullscreenCandidateQuad(resource_provider_
.get(),
960 pass
->shared_quad_state_list
.back(),
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);
973 Mock::VerifyAndClearExpectations(renderer_
.get());
974 Mock::VerifyAndClearExpectations(&scheduler_
);
977 TEST_F(GLRendererWithOverlaysTest
, NoValidatorNoOverlay
) {
978 bool use_validator
= false;
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(),
989 CreateFullscreenCheckeredQuad(resource_provider_
.get(),
990 pass
->shared_quad_state_list
.back(),
992 CreateFullscreenCheckeredQuad(resource_provider_
.get(),
993 pass
->shared_quad_state_list
.back(),
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);
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
));
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
));
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
));
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
));
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
));
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
));
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
));
1100 EXPECT_FALSE(resource_provider_
->InUseByConsumer(resource1
));
1101 Mock::VerifyAndClearExpectations(&scheduler_
);