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
->UpdateDrawProperties(false);
118 // We don't have a frame yet, so the video doesn't occlude the layer below it.
119 EXPECT_FALSE(draw_properties
.occlusion_in_content_space
.IsOccluded(visible
));
121 scoped_refptr
<media::VideoFrame
> video_frame
= media::VideoFrame::CreateFrame(
122 media::VideoFrame::YV12
, gfx::Size(10, 10), gfx::Rect(10, 10),
123 gfx::Size(10, 10), base::TimeDelta());
124 provider
.set_frame(video_frame
);
125 active_tree
->set_needs_update_draw_properties();
126 active_tree
->UpdateDrawProperties(false);
128 // We have a frame now, so the video occludes the layer below it.
129 EXPECT_TRUE(draw_properties
.occlusion_in_content_space
.IsOccluded(visible
));
132 TEST(VideoLayerImplTest
, DidBecomeActiveShouldSetActiveVideoLayer
) {
133 LayerTestCommon::LayerImplTest impl
;
134 DebugSetImplThreadAndMainThreadBlocked(impl
.proxy());
136 FakeVideoFrameProvider provider
;
137 VideoLayerImpl
* video_layer_impl
=
138 impl
.AddChildToRoot
<VideoLayerImpl
>(&provider
, media::VIDEO_ROTATION_0
);
140 VideoFrameProviderClientImpl
* client
=
141 static_cast<VideoFrameProviderClientImpl
*>(provider
.client());
144 EXPECT_FALSE(client
->ActiveVideoLayer());
145 video_layer_impl
->DidBecomeActive();
146 EXPECT_EQ(video_layer_impl
, client
->ActiveVideoLayer());
149 TEST(VideoLayerImplTest
, Rotated0
) {
150 gfx::Size
layer_size(100, 50);
151 gfx::Size
viewport_size(1000, 500);
153 LayerTestCommon::LayerImplTest impl
;
154 DebugSetImplThreadAndMainThreadBlocked(impl
.proxy());
156 scoped_refptr
<media::VideoFrame
> video_frame
=
157 media::VideoFrame::CreateFrame(media::VideoFrame::YV12
,
162 FakeVideoFrameProvider provider
;
163 provider
.set_frame(video_frame
);
165 VideoLayerImpl
* video_layer_impl
=
166 impl
.AddChildToRoot
<VideoLayerImpl
>(&provider
, media::VIDEO_ROTATION_0
);
167 video_layer_impl
->SetBounds(layer_size
);
168 video_layer_impl
->SetContentBounds(layer_size
);
169 video_layer_impl
->SetDrawsContent(true);
171 impl
.CalcDrawProps(viewport_size
);
173 impl
.AppendQuadsWithOcclusion(video_layer_impl
, occluded
);
175 EXPECT_EQ(1u, impl
.quad_list().size());
177 gfx::Point3F
p1(0, impl
.quad_list().front()->rect
.height(), 0);
178 gfx::Point3F
p2(impl
.quad_list().front()->rect
.width(), 0, 0);
179 impl
.quad_list().front()->quadTransform().TransformPoint(&p1
);
180 impl
.quad_list().front()->quadTransform().TransformPoint(&p2
);
181 EXPECT_EQ(gfx::Point3F(0, 50, 0), p1
);
182 EXPECT_EQ(gfx::Point3F(100, 0, 0), p2
);
185 TEST(VideoLayerImplTest
, Rotated90
) {
186 gfx::Size
layer_size(100, 50);
187 gfx::Size
viewport_size(1000, 500);
189 LayerTestCommon::LayerImplTest impl
;
190 DebugSetImplThreadAndMainThreadBlocked(impl
.proxy());
192 scoped_refptr
<media::VideoFrame
> video_frame
=
193 media::VideoFrame::CreateFrame(media::VideoFrame::YV12
,
198 FakeVideoFrameProvider provider
;
199 provider
.set_frame(video_frame
);
201 VideoLayerImpl
* video_layer_impl
=
202 impl
.AddChildToRoot
<VideoLayerImpl
>(&provider
, media::VIDEO_ROTATION_90
);
203 video_layer_impl
->SetBounds(layer_size
);
204 video_layer_impl
->SetContentBounds(layer_size
);
205 video_layer_impl
->SetDrawsContent(true);
207 impl
.CalcDrawProps(viewport_size
);
209 impl
.AppendQuadsWithOcclusion(video_layer_impl
, occluded
);
211 EXPECT_EQ(1u, impl
.quad_list().size());
213 gfx::Point3F
p1(0, impl
.quad_list().front()->rect
.height(), 0);
214 gfx::Point3F
p2(impl
.quad_list().front()->rect
.width(), 0, 0);
215 impl
.quad_list().front()->quadTransform().TransformPoint(&p1
);
216 impl
.quad_list().front()->quadTransform().TransformPoint(&p2
);
217 EXPECT_EQ(gfx::Point3F(0, 0, 0), p1
);
218 EXPECT_EQ(gfx::Point3F(100, 50, 0), p2
);
221 TEST(VideoLayerImplTest
, Rotated180
) {
222 gfx::Size
layer_size(100, 50);
223 gfx::Size
viewport_size(1000, 500);
225 LayerTestCommon::LayerImplTest impl
;
226 DebugSetImplThreadAndMainThreadBlocked(impl
.proxy());
228 scoped_refptr
<media::VideoFrame
> video_frame
=
229 media::VideoFrame::CreateFrame(media::VideoFrame::YV12
,
234 FakeVideoFrameProvider provider
;
235 provider
.set_frame(video_frame
);
237 VideoLayerImpl
* video_layer_impl
=
238 impl
.AddChildToRoot
<VideoLayerImpl
>(&provider
, media::VIDEO_ROTATION_180
);
239 video_layer_impl
->SetBounds(layer_size
);
240 video_layer_impl
->SetContentBounds(layer_size
);
241 video_layer_impl
->SetDrawsContent(true);
243 impl
.CalcDrawProps(viewport_size
);
245 impl
.AppendQuadsWithOcclusion(video_layer_impl
, occluded
);
247 EXPECT_EQ(1u, impl
.quad_list().size());
249 gfx::Point3F
p1(0, impl
.quad_list().front()->rect
.height(), 0);
250 gfx::Point3F
p2(impl
.quad_list().front()->rect
.width(), 0, 0);
251 impl
.quad_list().front()->quadTransform().TransformPoint(&p1
);
252 impl
.quad_list().front()->quadTransform().TransformPoint(&p2
);
253 EXPECT_EQ(gfx::Point3F(100, 0, 0), p1
);
254 EXPECT_EQ(gfx::Point3F(0, 50, 0), p2
);
257 TEST(VideoLayerImplTest
, Rotated270
) {
258 gfx::Size
layer_size(100, 50);
259 gfx::Size
viewport_size(1000, 500);
261 LayerTestCommon::LayerImplTest impl
;
262 DebugSetImplThreadAndMainThreadBlocked(impl
.proxy());
264 scoped_refptr
<media::VideoFrame
> video_frame
=
265 media::VideoFrame::CreateFrame(media::VideoFrame::YV12
,
270 FakeVideoFrameProvider provider
;
271 provider
.set_frame(video_frame
);
273 VideoLayerImpl
* video_layer_impl
=
274 impl
.AddChildToRoot
<VideoLayerImpl
>(&provider
, media::VIDEO_ROTATION_270
);
275 video_layer_impl
->SetBounds(layer_size
);
276 video_layer_impl
->SetContentBounds(layer_size
);
277 video_layer_impl
->SetDrawsContent(true);
279 impl
.CalcDrawProps(viewport_size
);
281 impl
.AppendQuadsWithOcclusion(video_layer_impl
, occluded
);
283 EXPECT_EQ(1u, impl
.quad_list().size());
285 gfx::Point3F
p1(0, impl
.quad_list().front()->rect
.height(), 0);
286 gfx::Point3F
p2(impl
.quad_list().front()->rect
.width(), 0, 0);
287 impl
.quad_list().front()->quadTransform().TransformPoint(&p1
);
288 impl
.quad_list().front()->quadTransform().TransformPoint(&p2
);
289 EXPECT_EQ(gfx::Point3F(100, 50, 0), p1
);
290 EXPECT_EQ(gfx::Point3F(0, 0, 0), p2
);
293 void EmptyCallback(unsigned sync_point
) {
296 TEST(VideoLayerImplTest
, SoftwareVideoFrameGeneratesYUVQuad
) {
297 gfx::Size
layer_size(1000, 1000);
298 gfx::Size
viewport_size(1000, 1000);
300 LayerTestCommon::LayerImplTest impl
;
301 DebugSetImplThreadAndMainThreadBlocked(impl
.proxy());
303 gpu::MailboxHolder mailbox_holder
;
304 mailbox_holder
.mailbox
.name
[0] = 1;
306 scoped_refptr
<media::VideoFrame
> video_frame
= media::VideoFrame::CreateFrame(
307 media::VideoFrame::YV12
, gfx::Size(20, 10), gfx::Rect(20, 10),
308 gfx::Size(20, 10), base::TimeDelta());
310 FakeVideoFrameProvider provider
;
311 provider
.set_frame(video_frame
);
313 VideoLayerImpl
* video_layer_impl
=
314 impl
.AddChildToRoot
<VideoLayerImpl
>(&provider
, media::VIDEO_ROTATION_0
);
315 video_layer_impl
->SetBounds(layer_size
);
316 video_layer_impl
->SetContentBounds(layer_size
);
317 video_layer_impl
->SetDrawsContent(true);
320 impl
.AppendQuadsWithOcclusion(video_layer_impl
, occluded
);
322 EXPECT_EQ(1u, impl
.quad_list().size());
323 const DrawQuad
* draw_quad
= impl
.quad_list().ElementAt(0);
324 ASSERT_EQ(DrawQuad::YUV_VIDEO_CONTENT
, draw_quad
->material
);
326 const YUVVideoDrawQuad
* yuv_draw_quad
=
327 static_cast<const YUVVideoDrawQuad
*>(draw_quad
);
328 EXPECT_EQ(yuv_draw_quad
->uv_tex_size
.height(),
329 (yuv_draw_quad
->ya_tex_size
.height() + 1) / 2);
330 EXPECT_EQ(yuv_draw_quad
->uv_tex_size
.width(),
331 (yuv_draw_quad
->ya_tex_size
.width() + 1) / 2);
334 TEST(VideoLayerImplTest
, NativeYUVFrameGeneratesYUVQuad
) {
335 gfx::Size
layer_size(1000, 1000);
336 gfx::Size
viewport_size(1000, 1000);
338 LayerTestCommon::LayerImplTest impl
;
339 DebugSetImplThreadAndMainThreadBlocked(impl
.proxy());
341 gpu::MailboxHolder mailbox_holder
;
342 mailbox_holder
.mailbox
.name
[0] = 1;
344 scoped_refptr
<media::VideoFrame
> video_frame
=
345 media::VideoFrame::WrapYUV420NativeTextures(
346 mailbox_holder
, mailbox_holder
, mailbox_holder
,
347 base::Bind(EmptyCallback
), gfx::Size(10, 10), gfx::Rect(10, 10),
348 gfx::Size(10, 10), base::TimeDelta(), true);
349 FakeVideoFrameProvider provider
;
350 provider
.set_frame(video_frame
);
352 VideoLayerImpl
* video_layer_impl
=
353 impl
.AddChildToRoot
<VideoLayerImpl
>(&provider
, media::VIDEO_ROTATION_0
);
354 video_layer_impl
->SetBounds(layer_size
);
355 video_layer_impl
->SetContentBounds(layer_size
);
356 video_layer_impl
->SetDrawsContent(true);
359 impl
.AppendQuadsWithOcclusion(video_layer_impl
, occluded
);
361 EXPECT_EQ(1u, impl
.quad_list().size());
362 const DrawQuad
* draw_quad
= impl
.quad_list().ElementAt(0);
363 ASSERT_EQ(DrawQuad::YUV_VIDEO_CONTENT
, draw_quad
->material
);
365 const YUVVideoDrawQuad
* yuv_draw_quad
=
366 static_cast<const YUVVideoDrawQuad
*>(draw_quad
);
367 EXPECT_EQ(yuv_draw_quad
->uv_tex_size
.height(),
368 (yuv_draw_quad
->ya_tex_size
.height() + 1) / 2);
369 EXPECT_EQ(yuv_draw_quad
->uv_tex_size
.width(),
370 (yuv_draw_quad
->ya_tex_size
.width() + 1) / 2);