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/layers/video_layer_impl.h"
7 #include "cc/layers/video_frame_provider_client_impl.h"
8 #include "cc/output/context_provider.h"
9 #include "cc/output/output_surface.h"
10 #include "cc/quads/draw_quad.h"
11 #include "cc/quads/yuv_video_draw_quad.h"
12 #include "cc/test/fake_video_frame_provider.h"
13 #include "cc/test/layer_test_common.h"
14 #include "cc/trees/single_thread_proxy.h"
15 #include "media/base/video_frame.h"
16 #include "testing/gtest/include/gtest/gtest.h"
21 // NOTE: We cannot use DebugScopedSetImplThreadAndMainThreadBlocked in these
22 // tests because it gets destroyed before the VideoLayerImpl is destroyed. This
23 // causes a DCHECK in VideoLayerImpl's destructor to fail.
24 static void DebugSetImplThreadAndMainThreadBlocked(Proxy
* proxy
) {
26 proxy
->SetCurrentThreadIsImplThread(true);
27 proxy
->SetMainThreadBlocked(true);
31 TEST(VideoLayerImplTest
, Occlusion
) {
32 gfx::Size
layer_size(1000, 1000);
33 gfx::Size
viewport_size(1000, 1000);
35 LayerTestCommon::LayerImplTest impl
;
36 DebugSetImplThreadAndMainThreadBlocked(impl
.proxy());
38 scoped_refptr
<media::VideoFrame
> video_frame
=
39 media::VideoFrame::CreateFrame(media::VideoFrame::YV12
,
44 FakeVideoFrameProvider provider
;
45 provider
.set_frame(video_frame
);
47 VideoLayerImpl
* video_layer_impl
=
48 impl
.AddChildToRoot
<VideoLayerImpl
>(&provider
, media::VIDEO_ROTATION_0
);
49 video_layer_impl
->SetBounds(layer_size
);
50 video_layer_impl
->SetContentBounds(layer_size
);
51 video_layer_impl
->SetDrawsContent(true);
53 impl
.CalcDrawProps(viewport_size
);
56 SCOPED_TRACE("No occlusion");
58 impl
.AppendQuadsWithOcclusion(video_layer_impl
, occluded
);
60 LayerTestCommon::VerifyQuadsExactlyCoverRect(impl
.quad_list(),
61 gfx::Rect(layer_size
));
62 EXPECT_EQ(1u, impl
.quad_list().size());
66 SCOPED_TRACE("Full occlusion");
67 gfx::Rect
occluded(video_layer_impl
->visible_content_rect());
68 impl
.AppendQuadsWithOcclusion(video_layer_impl
, occluded
);
70 LayerTestCommon::VerifyQuadsExactlyCoverRect(impl
.quad_list(), gfx::Rect());
71 EXPECT_EQ(impl
.quad_list().size(), 0u);
75 SCOPED_TRACE("Partial occlusion");
76 gfx::Rect
occluded(200, 0, 800, 1000);
77 impl
.AppendQuadsWithOcclusion(video_layer_impl
, occluded
);
79 size_t partially_occluded_count
= 0;
80 LayerTestCommon::VerifyQuadsAreOccluded(
81 impl
.quad_list(), occluded
, &partially_occluded_count
);
82 // The layer outputs one quad, which is partially occluded.
83 EXPECT_EQ(1u, impl
.quad_list().size());
84 EXPECT_EQ(1u, partially_occluded_count
);
88 TEST(VideoLayerImplTest
, OccludesOtherLayers
) {
89 gfx::Size
layer_size(1000, 1000);
90 gfx::Rect
visible(layer_size
);
92 LayerTestCommon::LayerImplTest impl
;
93 impl
.host_impl()->SetViewportSize(layer_size
);
94 DebugSetImplThreadAndMainThreadBlocked(impl
.proxy());
95 auto active_tree
= impl
.host_impl()->active_tree();
97 // Create a video layer with no frame on top of another layer.
98 scoped_ptr
<LayerImpl
> layer_impl
= LayerImpl::Create(active_tree
, 3);
99 layer_impl
->SetHasRenderSurface(true);
100 layer_impl
->SetBounds(layer_size
);
101 layer_impl
->SetContentBounds(layer_size
);
102 layer_impl
->SetDrawsContent(true);
103 const auto& draw_properties
= layer_impl
->draw_properties();
105 FakeVideoFrameProvider provider
;
106 scoped_ptr
<VideoLayerImpl
> video_layer_impl
= VideoLayerImpl::Create(
107 active_tree
, 4, &provider
, media::VIDEO_ROTATION_0
);
108 video_layer_impl
->SetBounds(layer_size
);
109 video_layer_impl
->SetContentBounds(layer_size
);
110 video_layer_impl
->SetDrawsContent(true);
111 video_layer_impl
->SetContentsOpaque(true);
113 layer_impl
->AddChild(video_layer_impl
.Pass());
114 active_tree
->SetRootLayer(layer_impl
.Pass());
116 active_tree
->BuildPropertyTreesForTesting();
118 active_tree
->UpdateDrawProperties(false);
120 // We don't have a frame yet, so the video doesn't occlude the layer below it.
121 EXPECT_FALSE(draw_properties
.occlusion_in_content_space
.IsOccluded(visible
));
123 scoped_refptr
<media::VideoFrame
> video_frame
= media::VideoFrame::CreateFrame(
124 media::VideoFrame::YV12
, gfx::Size(10, 10), gfx::Rect(10, 10),
125 gfx::Size(10, 10), base::TimeDelta());
126 provider
.set_frame(video_frame
);
127 active_tree
->set_needs_update_draw_properties();
128 active_tree
->UpdateDrawProperties(false);
130 // We have a frame now, so the video occludes the layer below it.
131 EXPECT_TRUE(draw_properties
.occlusion_in_content_space
.IsOccluded(visible
));
134 TEST(VideoLayerImplTest
, DidBecomeActiveShouldSetActiveVideoLayer
) {
135 LayerTestCommon::LayerImplTest impl
;
136 DebugSetImplThreadAndMainThreadBlocked(impl
.proxy());
138 FakeVideoFrameProvider provider
;
139 VideoLayerImpl
* video_layer_impl
=
140 impl
.AddChildToRoot
<VideoLayerImpl
>(&provider
, media::VIDEO_ROTATION_0
);
142 VideoFrameProviderClientImpl
* client
=
143 static_cast<VideoFrameProviderClientImpl
*>(provider
.client());
146 EXPECT_FALSE(client
->ActiveVideoLayer());
147 video_layer_impl
->DidBecomeActive();
148 EXPECT_EQ(video_layer_impl
, client
->ActiveVideoLayer());
151 TEST(VideoLayerImplTest
, Rotated0
) {
152 gfx::Size
layer_size(100, 50);
153 gfx::Size
viewport_size(1000, 500);
155 LayerTestCommon::LayerImplTest impl
;
156 DebugSetImplThreadAndMainThreadBlocked(impl
.proxy());
158 scoped_refptr
<media::VideoFrame
> video_frame
=
159 media::VideoFrame::CreateFrame(media::VideoFrame::YV12
,
164 FakeVideoFrameProvider provider
;
165 provider
.set_frame(video_frame
);
167 VideoLayerImpl
* video_layer_impl
=
168 impl
.AddChildToRoot
<VideoLayerImpl
>(&provider
, media::VIDEO_ROTATION_0
);
169 video_layer_impl
->SetBounds(layer_size
);
170 video_layer_impl
->SetContentBounds(layer_size
);
171 video_layer_impl
->SetDrawsContent(true);
173 impl
.CalcDrawProps(viewport_size
);
175 impl
.AppendQuadsWithOcclusion(video_layer_impl
, occluded
);
177 EXPECT_EQ(1u, impl
.quad_list().size());
179 gfx::Point3F
p1(0, impl
.quad_list().front()->rect
.height(), 0);
180 gfx::Point3F
p2(impl
.quad_list().front()->rect
.width(), 0, 0);
181 impl
.quad_list().front()->quadTransform().TransformPoint(&p1
);
182 impl
.quad_list().front()->quadTransform().TransformPoint(&p2
);
183 EXPECT_EQ(gfx::Point3F(0, 50, 0), p1
);
184 EXPECT_EQ(gfx::Point3F(100, 0, 0), p2
);
187 TEST(VideoLayerImplTest
, Rotated90
) {
188 gfx::Size
layer_size(100, 50);
189 gfx::Size
viewport_size(1000, 500);
191 LayerTestCommon::LayerImplTest impl
;
192 DebugSetImplThreadAndMainThreadBlocked(impl
.proxy());
194 scoped_refptr
<media::VideoFrame
> video_frame
=
195 media::VideoFrame::CreateFrame(media::VideoFrame::YV12
,
200 FakeVideoFrameProvider provider
;
201 provider
.set_frame(video_frame
);
203 VideoLayerImpl
* video_layer_impl
=
204 impl
.AddChildToRoot
<VideoLayerImpl
>(&provider
, media::VIDEO_ROTATION_90
);
205 video_layer_impl
->SetBounds(layer_size
);
206 video_layer_impl
->SetContentBounds(layer_size
);
207 video_layer_impl
->SetDrawsContent(true);
209 impl
.CalcDrawProps(viewport_size
);
211 impl
.AppendQuadsWithOcclusion(video_layer_impl
, occluded
);
213 EXPECT_EQ(1u, impl
.quad_list().size());
215 gfx::Point3F
p1(0, impl
.quad_list().front()->rect
.height(), 0);
216 gfx::Point3F
p2(impl
.quad_list().front()->rect
.width(), 0, 0);
217 impl
.quad_list().front()->quadTransform().TransformPoint(&p1
);
218 impl
.quad_list().front()->quadTransform().TransformPoint(&p2
);
219 EXPECT_EQ(gfx::Point3F(0, 0, 0), p1
);
220 EXPECT_EQ(gfx::Point3F(100, 50, 0), p2
);
223 TEST(VideoLayerImplTest
, Rotated180
) {
224 gfx::Size
layer_size(100, 50);
225 gfx::Size
viewport_size(1000, 500);
227 LayerTestCommon::LayerImplTest impl
;
228 DebugSetImplThreadAndMainThreadBlocked(impl
.proxy());
230 scoped_refptr
<media::VideoFrame
> video_frame
=
231 media::VideoFrame::CreateFrame(media::VideoFrame::YV12
,
236 FakeVideoFrameProvider provider
;
237 provider
.set_frame(video_frame
);
239 VideoLayerImpl
* video_layer_impl
=
240 impl
.AddChildToRoot
<VideoLayerImpl
>(&provider
, media::VIDEO_ROTATION_180
);
241 video_layer_impl
->SetBounds(layer_size
);
242 video_layer_impl
->SetContentBounds(layer_size
);
243 video_layer_impl
->SetDrawsContent(true);
245 impl
.CalcDrawProps(viewport_size
);
247 impl
.AppendQuadsWithOcclusion(video_layer_impl
, occluded
);
249 EXPECT_EQ(1u, impl
.quad_list().size());
251 gfx::Point3F
p1(0, impl
.quad_list().front()->rect
.height(), 0);
252 gfx::Point3F
p2(impl
.quad_list().front()->rect
.width(), 0, 0);
253 impl
.quad_list().front()->quadTransform().TransformPoint(&p1
);
254 impl
.quad_list().front()->quadTransform().TransformPoint(&p2
);
255 EXPECT_EQ(gfx::Point3F(100, 0, 0), p1
);
256 EXPECT_EQ(gfx::Point3F(0, 50, 0), p2
);
259 TEST(VideoLayerImplTest
, Rotated270
) {
260 gfx::Size
layer_size(100, 50);
261 gfx::Size
viewport_size(1000, 500);
263 LayerTestCommon::LayerImplTest impl
;
264 DebugSetImplThreadAndMainThreadBlocked(impl
.proxy());
266 scoped_refptr
<media::VideoFrame
> video_frame
=
267 media::VideoFrame::CreateFrame(media::VideoFrame::YV12
,
272 FakeVideoFrameProvider provider
;
273 provider
.set_frame(video_frame
);
275 VideoLayerImpl
* video_layer_impl
=
276 impl
.AddChildToRoot
<VideoLayerImpl
>(&provider
, media::VIDEO_ROTATION_270
);
277 video_layer_impl
->SetBounds(layer_size
);
278 video_layer_impl
->SetContentBounds(layer_size
);
279 video_layer_impl
->SetDrawsContent(true);
281 impl
.CalcDrawProps(viewport_size
);
283 impl
.AppendQuadsWithOcclusion(video_layer_impl
, occluded
);
285 EXPECT_EQ(1u, impl
.quad_list().size());
287 gfx::Point3F
p1(0, impl
.quad_list().front()->rect
.height(), 0);
288 gfx::Point3F
p2(impl
.quad_list().front()->rect
.width(), 0, 0);
289 impl
.quad_list().front()->quadTransform().TransformPoint(&p1
);
290 impl
.quad_list().front()->quadTransform().TransformPoint(&p2
);
291 EXPECT_EQ(gfx::Point3F(100, 50, 0), p1
);
292 EXPECT_EQ(gfx::Point3F(0, 0, 0), p2
);
295 void EmptyCallback(unsigned sync_point
) {
298 TEST(VideoLayerImplTest
, SoftwareVideoFrameGeneratesYUVQuad
) {
299 gfx::Size
layer_size(1000, 1000);
300 gfx::Size
viewport_size(1000, 1000);
302 LayerTestCommon::LayerImplTest impl
;
303 DebugSetImplThreadAndMainThreadBlocked(impl
.proxy());
305 gpu::MailboxHolder mailbox_holder
;
306 mailbox_holder
.mailbox
.name
[0] = 1;
308 scoped_refptr
<media::VideoFrame
> video_frame
= media::VideoFrame::CreateFrame(
309 media::VideoFrame::YV12
, gfx::Size(20, 10), gfx::Rect(20, 10),
310 gfx::Size(20, 10), base::TimeDelta());
312 FakeVideoFrameProvider provider
;
313 provider
.set_frame(video_frame
);
315 VideoLayerImpl
* video_layer_impl
=
316 impl
.AddChildToRoot
<VideoLayerImpl
>(&provider
, media::VIDEO_ROTATION_0
);
317 video_layer_impl
->SetBounds(layer_size
);
318 video_layer_impl
->SetContentBounds(layer_size
);
319 video_layer_impl
->SetDrawsContent(true);
322 impl
.AppendQuadsWithOcclusion(video_layer_impl
, occluded
);
324 EXPECT_EQ(1u, impl
.quad_list().size());
325 const DrawQuad
* draw_quad
= impl
.quad_list().ElementAt(0);
326 ASSERT_EQ(DrawQuad::YUV_VIDEO_CONTENT
, draw_quad
->material
);
328 const YUVVideoDrawQuad
* yuv_draw_quad
=
329 static_cast<const YUVVideoDrawQuad
*>(draw_quad
);
330 EXPECT_EQ(yuv_draw_quad
->uv_tex_size
.height(),
331 (yuv_draw_quad
->ya_tex_size
.height() + 1) / 2);
332 EXPECT_EQ(yuv_draw_quad
->uv_tex_size
.width(),
333 (yuv_draw_quad
->ya_tex_size
.width() + 1) / 2);
336 TEST(VideoLayerImplTest
, NativeYUVFrameGeneratesYUVQuad
) {
337 gfx::Size
layer_size(1000, 1000);
338 gfx::Size
viewport_size(1000, 1000);
340 LayerTestCommon::LayerImplTest impl
;
341 DebugSetImplThreadAndMainThreadBlocked(impl
.proxy());
343 gpu::MailboxHolder mailbox_holder
;
344 mailbox_holder
.mailbox
.name
[0] = 1;
346 scoped_refptr
<media::VideoFrame
> video_frame
=
347 media::VideoFrame::WrapYUV420NativeTextures(
348 mailbox_holder
, mailbox_holder
, mailbox_holder
,
349 base::Bind(EmptyCallback
), gfx::Size(10, 10), gfx::Rect(10, 10),
350 gfx::Size(10, 10), base::TimeDelta(), true);
351 FakeVideoFrameProvider provider
;
352 provider
.set_frame(video_frame
);
354 VideoLayerImpl
* video_layer_impl
=
355 impl
.AddChildToRoot
<VideoLayerImpl
>(&provider
, media::VIDEO_ROTATION_0
);
356 video_layer_impl
->SetBounds(layer_size
);
357 video_layer_impl
->SetContentBounds(layer_size
);
358 video_layer_impl
->SetDrawsContent(true);
361 impl
.AppendQuadsWithOcclusion(video_layer_impl
, occluded
);
363 EXPECT_EQ(1u, impl
.quad_list().size());
364 const DrawQuad
* draw_quad
= impl
.quad_list().ElementAt(0);
365 ASSERT_EQ(DrawQuad::YUV_VIDEO_CONTENT
, draw_quad
->material
);
367 const YUVVideoDrawQuad
* yuv_draw_quad
=
368 static_cast<const YUVVideoDrawQuad
*>(draw_quad
);
369 EXPECT_EQ(yuv_draw_quad
->uv_tex_size
.height(),
370 (yuv_draw_quad
->ya_tex_size
.height() + 1) / 2);
371 EXPECT_EQ(yuv_draw_quad
->uv_tex_size
.width(),
372 (yuv_draw_quad
->ya_tex_size
.width() + 1) / 2);