video_layer_impl_unittest.cc 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  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.
  4. #include "cc/layers/video_layer_impl.h"
  5. #include <stddef.h>
  6. #include "base/callback_helpers.h"
  7. #include "cc/layers/video_frame_provider_client_impl.h"
  8. #include "cc/test/fake_video_frame_provider.h"
  9. #include "cc/test/layer_tree_impl_test_base.h"
  10. #include "cc/trees/single_thread_proxy.h"
  11. #include "components/viz/common/gpu/context_provider.h"
  12. #include "components/viz/common/quads/draw_quad.h"
  13. #include "components/viz/common/quads/texture_draw_quad.h"
  14. #include "components/viz/common/quads/yuv_video_draw_quad.h"
  15. #include "components/viz/service/display/output_surface.h"
  16. #include "media/base/video_frame.h"
  17. #include "testing/gtest/include/gtest/gtest.h"
  18. namespace cc {
  19. namespace {
  20. // NOTE: We cannot use DebugScopedSetImplThreadAndMainThreadBlocked in these
  21. // tests because it gets destroyed before the VideoLayerImpl is destroyed. This
  22. // causes a DCHECK in VideoLayerImpl's destructor to fail.
  23. static void DebugSetImplThreadAndMainThreadBlocked(
  24. TaskRunnerProvider* task_runner_provider) {
  25. #if DCHECK_IS_ON()
  26. task_runner_provider->SetCurrentThreadIsImplThread(true);
  27. task_runner_provider->SetMainThreadBlocked(true);
  28. #endif
  29. }
  30. TEST(VideoLayerImplTest, Occlusion) {
  31. gfx::Size layer_size(1000, 1000);
  32. gfx::Size viewport_size(1000, 1000);
  33. LayerTreeImplTestBase impl;
  34. DebugSetImplThreadAndMainThreadBlocked(impl.task_runner_provider());
  35. scoped_refptr<media::VideoFrame> video_frame = media::VideoFrame::CreateFrame(
  36. media::PIXEL_FORMAT_I420, gfx::Size(10, 10), gfx::Rect(10, 10),
  37. gfx::Size(10, 10), base::TimeDelta());
  38. FakeVideoFrameProvider provider;
  39. provider.set_frame(video_frame);
  40. VideoLayerImpl* video_layer_impl =
  41. impl.AddLayer<VideoLayerImpl>(&provider, media::VIDEO_ROTATION_0);
  42. video_layer_impl->SetBounds(layer_size);
  43. video_layer_impl->SetDrawsContent(true);
  44. video_layer_impl->set_visible_layer_rect(gfx::Rect(layer_size));
  45. CopyProperties(impl.root_layer(), video_layer_impl);
  46. impl.CalcDrawProps(viewport_size);
  47. {
  48. SCOPED_TRACE("No occlusion");
  49. gfx::Rect occluded;
  50. impl.AppendQuadsWithOcclusion(video_layer_impl, occluded);
  51. VerifyQuadsExactlyCoverRect(impl.quad_list(), gfx::Rect(layer_size));
  52. VerifyQuadsExactlyCoverRect(
  53. impl.quad_list(),
  54. impl.quad_list().cbegin()->shared_quad_state->visible_quad_layer_rect);
  55. EXPECT_EQ(1u, impl.quad_list().size());
  56. }
  57. {
  58. SCOPED_TRACE("Full occlusion");
  59. gfx::Rect occluded(video_layer_impl->visible_layer_rect());
  60. impl.AppendQuadsWithOcclusion(video_layer_impl, occluded);
  61. VerifyQuadsExactlyCoverRect(impl.quad_list(), gfx::Rect());
  62. EXPECT_EQ(impl.quad_list().size(), 0u);
  63. }
  64. {
  65. SCOPED_TRACE("Partial occlusion");
  66. gfx::Rect occluded(200, 0, 800, 1000);
  67. impl.AppendQuadsWithOcclusion(video_layer_impl, occluded);
  68. size_t partially_occluded_count = 0;
  69. VerifyQuadsAreOccluded(impl.quad_list(), occluded,
  70. &partially_occluded_count);
  71. VerifyQuadsExactlyCoverRect(
  72. impl.quad_list(),
  73. impl.quad_list().cbegin()->shared_quad_state->visible_quad_layer_rect);
  74. // The layer outputs one quad, which is partially occluded.
  75. EXPECT_EQ(1u, impl.quad_list().size());
  76. EXPECT_EQ(1u, partially_occluded_count);
  77. }
  78. }
  79. TEST(VideoLayerImplTest, OccludesOtherLayers) {
  80. gfx::Size layer_size(1000, 1000);
  81. gfx::Rect visible(layer_size);
  82. LayerTreeImplTestBase impl;
  83. impl.host_impl()->active_tree()->SetDeviceViewportRect(visible);
  84. DebugSetImplThreadAndMainThreadBlocked(impl.task_runner_provider());
  85. auto* active_tree = impl.host_impl()->active_tree();
  86. // Create a video layer with no frame on top of another layer.
  87. LayerImpl* root = impl.root_layer();
  88. root->SetBounds(layer_size);
  89. root->SetDrawsContent(true);
  90. const auto& draw_properties = root->draw_properties();
  91. FakeVideoFrameProvider provider;
  92. VideoLayerImpl* video_layer_impl =
  93. impl.AddLayer<VideoLayerImpl>(&provider, media::VIDEO_ROTATION_0);
  94. video_layer_impl->SetBounds(layer_size);
  95. video_layer_impl->SetDrawsContent(true);
  96. video_layer_impl->SetContentsOpaque(true);
  97. CopyProperties(root, video_layer_impl);
  98. impl.CalcDrawProps(layer_size);
  99. // We don't have a frame yet, so the video doesn't occlude the layer below it.
  100. EXPECT_FALSE(draw_properties.occlusion_in_content_space.IsOccluded(visible));
  101. scoped_refptr<media::VideoFrame> video_frame = media::VideoFrame::CreateFrame(
  102. media::PIXEL_FORMAT_I420, gfx::Size(10, 10), gfx::Rect(10, 10),
  103. gfx::Size(10, 10), base::TimeDelta());
  104. provider.set_frame(video_frame);
  105. active_tree->set_needs_update_draw_properties();
  106. active_tree->UpdateDrawProperties();
  107. // We have a frame now, so the video occludes the layer below it.
  108. EXPECT_TRUE(draw_properties.occlusion_in_content_space.IsOccluded(visible));
  109. }
  110. TEST(VideoLayerImplTest, DidBecomeActiveShouldSetActiveVideoLayer) {
  111. LayerTreeImplTestBase impl;
  112. DebugSetImplThreadAndMainThreadBlocked(impl.task_runner_provider());
  113. FakeVideoFrameProvider provider;
  114. VideoLayerImpl* video_layer_impl =
  115. impl.AddLayer<VideoLayerImpl>(&provider, media::VIDEO_ROTATION_0);
  116. CopyProperties(impl.root_layer(), video_layer_impl);
  117. VideoFrameProviderClientImpl* client =
  118. static_cast<VideoFrameProviderClientImpl*>(provider.client());
  119. ASSERT_TRUE(client);
  120. EXPECT_FALSE(client->ActiveVideoLayer());
  121. video_layer_impl->DidBecomeActive();
  122. EXPECT_EQ(video_layer_impl, client->ActiveVideoLayer());
  123. }
  124. TEST(VideoLayerImplTest, Rotated0) {
  125. gfx::Size layer_size(100, 50);
  126. gfx::Size viewport_size(1000, 500);
  127. LayerTreeImplTestBase impl;
  128. DebugSetImplThreadAndMainThreadBlocked(impl.task_runner_provider());
  129. scoped_refptr<media::VideoFrame> video_frame = media::VideoFrame::CreateFrame(
  130. media::PIXEL_FORMAT_I420, gfx::Size(20, 10), gfx::Rect(20, 10),
  131. gfx::Size(20, 10), base::TimeDelta());
  132. FakeVideoFrameProvider provider;
  133. provider.set_frame(video_frame);
  134. VideoLayerImpl* video_layer_impl =
  135. impl.AddLayer<VideoLayerImpl>(&provider, media::VIDEO_ROTATION_0);
  136. video_layer_impl->SetBounds(layer_size);
  137. video_layer_impl->SetDrawsContent(true);
  138. CopyProperties(impl.root_layer(), video_layer_impl);
  139. impl.CalcDrawProps(viewport_size);
  140. gfx::Rect occluded;
  141. impl.AppendQuadsWithOcclusion(video_layer_impl, occluded);
  142. EXPECT_EQ(1u, impl.quad_list().size());
  143. gfx::Point3F p1(0, impl.quad_list().front()->rect.height(), 0);
  144. gfx::Point3F p2(impl.quad_list().front()->rect.width(), 0, 0);
  145. impl.quad_list()
  146. .front()
  147. ->shared_quad_state->quad_to_target_transform.TransformPoint(&p1);
  148. impl.quad_list()
  149. .front()
  150. ->shared_quad_state->quad_to_target_transform.TransformPoint(&p2);
  151. EXPECT_EQ(gfx::Point3F(0, 50, 0), p1);
  152. EXPECT_EQ(gfx::Point3F(100, 0, 0), p2);
  153. }
  154. TEST(VideoLayerImplTest, Rotated90) {
  155. gfx::Size layer_size(100, 50);
  156. gfx::Size viewport_size(1000, 500);
  157. LayerTreeImplTestBase impl;
  158. DebugSetImplThreadAndMainThreadBlocked(impl.task_runner_provider());
  159. scoped_refptr<media::VideoFrame> video_frame = media::VideoFrame::CreateFrame(
  160. media::PIXEL_FORMAT_I420, gfx::Size(20, 10), gfx::Rect(20, 10),
  161. gfx::Size(20, 10), base::TimeDelta());
  162. FakeVideoFrameProvider provider;
  163. provider.set_frame(video_frame);
  164. VideoLayerImpl* video_layer_impl =
  165. impl.AddLayer<VideoLayerImpl>(&provider, media::VIDEO_ROTATION_90);
  166. video_layer_impl->SetBounds(layer_size);
  167. video_layer_impl->SetDrawsContent(true);
  168. CopyProperties(impl.root_layer(), video_layer_impl);
  169. impl.CalcDrawProps(viewport_size);
  170. gfx::Rect occluded;
  171. impl.AppendQuadsWithOcclusion(video_layer_impl, occluded);
  172. EXPECT_EQ(1u, impl.quad_list().size());
  173. gfx::Point3F p1(0, impl.quad_list().front()->rect.height(), 0);
  174. gfx::Point3F p2(impl.quad_list().front()->rect.width(), 0, 0);
  175. impl.quad_list()
  176. .front()
  177. ->shared_quad_state->quad_to_target_transform.TransformPoint(&p1);
  178. impl.quad_list()
  179. .front()
  180. ->shared_quad_state->quad_to_target_transform.TransformPoint(&p2);
  181. EXPECT_EQ(gfx::Point3F(0, 0, 0), p1);
  182. EXPECT_EQ(gfx::Point3F(100, 50, 0), p2);
  183. }
  184. TEST(VideoLayerImplTest, Rotated180) {
  185. gfx::Size layer_size(100, 50);
  186. gfx::Size viewport_size(1000, 500);
  187. LayerTreeImplTestBase impl;
  188. DebugSetImplThreadAndMainThreadBlocked(impl.task_runner_provider());
  189. scoped_refptr<media::VideoFrame> video_frame = media::VideoFrame::CreateFrame(
  190. media::PIXEL_FORMAT_I420, gfx::Size(20, 10), gfx::Rect(20, 10),
  191. gfx::Size(20, 10), base::TimeDelta());
  192. FakeVideoFrameProvider provider;
  193. provider.set_frame(video_frame);
  194. VideoLayerImpl* video_layer_impl =
  195. impl.AddLayer<VideoLayerImpl>(&provider, media::VIDEO_ROTATION_180);
  196. video_layer_impl->SetBounds(layer_size);
  197. video_layer_impl->SetDrawsContent(true);
  198. CopyProperties(impl.root_layer(), video_layer_impl);
  199. impl.CalcDrawProps(viewport_size);
  200. gfx::Rect occluded;
  201. impl.AppendQuadsWithOcclusion(video_layer_impl, occluded);
  202. EXPECT_EQ(1u, impl.quad_list().size());
  203. gfx::Point3F p1(0, impl.quad_list().front()->rect.height(), 0);
  204. gfx::Point3F p2(impl.quad_list().front()->rect.width(), 0, 0);
  205. impl.quad_list()
  206. .front()
  207. ->shared_quad_state->quad_to_target_transform.TransformPoint(&p1);
  208. impl.quad_list()
  209. .front()
  210. ->shared_quad_state->quad_to_target_transform.TransformPoint(&p2);
  211. EXPECT_EQ(gfx::Point3F(100, 0, 0), p1);
  212. EXPECT_EQ(gfx::Point3F(0, 50, 0), p2);
  213. }
  214. TEST(VideoLayerImplTest, Rotated270) {
  215. gfx::Size layer_size(100, 50);
  216. gfx::Size viewport_size(1000, 500);
  217. LayerTreeImplTestBase impl;
  218. DebugSetImplThreadAndMainThreadBlocked(impl.task_runner_provider());
  219. scoped_refptr<media::VideoFrame> video_frame = media::VideoFrame::CreateFrame(
  220. media::PIXEL_FORMAT_I420, gfx::Size(20, 10), gfx::Rect(20, 10),
  221. gfx::Size(20, 10), base::TimeDelta());
  222. FakeVideoFrameProvider provider;
  223. provider.set_frame(video_frame);
  224. VideoLayerImpl* video_layer_impl =
  225. impl.AddLayer<VideoLayerImpl>(&provider, media::VIDEO_ROTATION_270);
  226. video_layer_impl->SetBounds(layer_size);
  227. video_layer_impl->SetDrawsContent(true);
  228. CopyProperties(impl.root_layer(), video_layer_impl);
  229. impl.CalcDrawProps(viewport_size);
  230. gfx::Rect occluded;
  231. impl.AppendQuadsWithOcclusion(video_layer_impl, occluded);
  232. EXPECT_EQ(1u, impl.quad_list().size());
  233. gfx::Point3F p1(0, impl.quad_list().front()->rect.height(), 0);
  234. gfx::Point3F p2(impl.quad_list().front()->rect.width(), 0, 0);
  235. impl.quad_list()
  236. .front()
  237. ->shared_quad_state->quad_to_target_transform.TransformPoint(&p1);
  238. impl.quad_list()
  239. .front()
  240. ->shared_quad_state->quad_to_target_transform.TransformPoint(&p2);
  241. EXPECT_EQ(gfx::Point3F(100, 50, 0), p1);
  242. EXPECT_EQ(gfx::Point3F(0, 0, 0), p2);
  243. }
  244. TEST(VideoLayerImplTest, SoftwareVideoFrameGeneratesYUVQuad) {
  245. gfx::Size layer_size(1000, 1000);
  246. LayerTreeImplTestBase impl;
  247. DebugSetImplThreadAndMainThreadBlocked(impl.task_runner_provider());
  248. gpu::MailboxHolder mailbox_holder;
  249. mailbox_holder.mailbox.name[0] = 1;
  250. scoped_refptr<media::VideoFrame> video_frame = media::VideoFrame::CreateFrame(
  251. media::PIXEL_FORMAT_I420, gfx::Size(20, 10), gfx::Rect(20, 10),
  252. gfx::Size(20, 10), base::TimeDelta());
  253. FakeVideoFrameProvider provider;
  254. provider.set_frame(video_frame);
  255. VideoLayerImpl* video_layer_impl =
  256. impl.AddLayer<VideoLayerImpl>(&provider, media::VIDEO_ROTATION_0);
  257. video_layer_impl->SetBounds(layer_size);
  258. video_layer_impl->SetDrawsContent(true);
  259. video_layer_impl->set_visible_layer_rect(gfx::Rect(layer_size));
  260. CopyProperties(impl.root_layer(), video_layer_impl);
  261. impl.CalcDrawProps(layer_size);
  262. gfx::Rect occluded;
  263. impl.AppendQuadsWithOcclusion(video_layer_impl, occluded);
  264. EXPECT_EQ(1u, impl.quad_list().size());
  265. const viz::DrawQuad* draw_quad = impl.quad_list().ElementAt(0);
  266. ASSERT_EQ(viz::DrawQuad::Material::kYuvVideoContent, draw_quad->material);
  267. const auto* yuv_draw_quad =
  268. static_cast<const viz::YUVVideoDrawQuad*>(draw_quad);
  269. EXPECT_EQ(yuv_draw_quad->uv_tex_size.height(),
  270. (yuv_draw_quad->ya_tex_size.height() + 1) / 2);
  271. EXPECT_EQ(yuv_draw_quad->uv_tex_size.width(),
  272. (yuv_draw_quad->ya_tex_size.width() + 1) / 2);
  273. }
  274. TEST(VideoLayerImplTest, HibitSoftwareVideoFrameGeneratesYUVQuad) {
  275. gfx::Size layer_size(1000, 1000);
  276. LayerTreeImplTestBase impl;
  277. DebugSetImplThreadAndMainThreadBlocked(impl.task_runner_provider());
  278. gpu::MailboxHolder mailbox_holder;
  279. mailbox_holder.mailbox.name[0] = 1;
  280. scoped_refptr<media::VideoFrame> video_frame = media::VideoFrame::CreateFrame(
  281. media::PIXEL_FORMAT_YUV420P10, gfx::Size(20, 10), gfx::Rect(20, 10),
  282. gfx::Size(20, 10), base::TimeDelta());
  283. FakeVideoFrameProvider provider;
  284. provider.set_frame(video_frame);
  285. VideoLayerImpl* video_layer_impl =
  286. impl.AddLayer<VideoLayerImpl>(&provider, media::VIDEO_ROTATION_0);
  287. video_layer_impl->SetBounds(layer_size);
  288. video_layer_impl->SetDrawsContent(true);
  289. video_layer_impl->set_visible_layer_rect(gfx::Rect(layer_size));
  290. CopyProperties(impl.root_layer(), video_layer_impl);
  291. impl.CalcDrawProps(layer_size);
  292. gfx::Rect occluded;
  293. impl.AppendQuadsWithOcclusion(video_layer_impl, occluded);
  294. EXPECT_EQ(1u, impl.quad_list().size());
  295. const viz::DrawQuad* draw_quad = impl.quad_list().ElementAt(0);
  296. ASSERT_EQ(viz::DrawQuad::Material::kYuvVideoContent, draw_quad->material);
  297. const auto* yuv_draw_quad =
  298. static_cast<const viz::YUVVideoDrawQuad*>(draw_quad);
  299. EXPECT_EQ(5, yuv_draw_quad->uv_tex_size.height());
  300. EXPECT_EQ(10, yuv_draw_quad->uv_tex_size.width());
  301. }
  302. TEST(VideoLayerImplTest, NativeYUVFrameGeneratesYUVQuad) {
  303. gfx::Size layer_size(1000, 1000);
  304. LayerTreeImplTestBase impl;
  305. DebugSetImplThreadAndMainThreadBlocked(impl.task_runner_provider());
  306. gpu::MailboxHolder mailbox_holders[media::VideoFrame::kMaxPlanes];
  307. mailbox_holders[0].mailbox.name[0] = 1;
  308. mailbox_holders[1].mailbox.name[0] = 1;
  309. mailbox_holders[2].mailbox.name[0] = 1;
  310. scoped_refptr<media::VideoFrame> video_frame =
  311. media::VideoFrame::WrapNativeTextures(
  312. media::PIXEL_FORMAT_I420, mailbox_holders, base::DoNothing(),
  313. gfx::Size(10, 10), gfx::Rect(10, 10), gfx::Size(10, 10),
  314. base::TimeDelta());
  315. ASSERT_TRUE(video_frame);
  316. video_frame->metadata().allow_overlay = true;
  317. FakeVideoFrameProvider provider;
  318. provider.set_frame(video_frame);
  319. VideoLayerImpl* video_layer_impl =
  320. impl.AddLayer<VideoLayerImpl>(&provider, media::VIDEO_ROTATION_0);
  321. video_layer_impl->SetBounds(layer_size);
  322. video_layer_impl->SetDrawsContent(true);
  323. video_layer_impl->set_visible_layer_rect(gfx::Rect(layer_size));
  324. CopyProperties(impl.root_layer(), video_layer_impl);
  325. impl.CalcDrawProps(layer_size);
  326. gfx::Rect occluded;
  327. impl.AppendQuadsWithOcclusion(video_layer_impl, occluded);
  328. EXPECT_EQ(1u, impl.quad_list().size());
  329. const viz::DrawQuad* draw_quad = impl.quad_list().ElementAt(0);
  330. ASSERT_EQ(viz::DrawQuad::Material::kYuvVideoContent, draw_quad->material);
  331. const auto* yuv_draw_quad =
  332. static_cast<const viz::YUVVideoDrawQuad*>(draw_quad);
  333. EXPECT_EQ(yuv_draw_quad->uv_tex_size.height(),
  334. (yuv_draw_quad->ya_tex_size.height() + 1) / 2);
  335. EXPECT_EQ(yuv_draw_quad->uv_tex_size.width(),
  336. (yuv_draw_quad->ya_tex_size.width() + 1) / 2);
  337. }
  338. TEST(VideoLayerImplTest, NativeARGBFrameGeneratesTextureQuad) {
  339. gfx::Size layer_size(1000, 1000);
  340. LayerTreeImplTestBase impl;
  341. DebugSetImplThreadAndMainThreadBlocked(impl.task_runner_provider());
  342. gpu::MailboxHolder mailbox_holders[media::VideoFrame::kMaxPlanes];
  343. mailbox_holders[0].texture_target = GL_TEXTURE_2D;
  344. mailbox_holders[0].mailbox.name[0] = 1;
  345. gfx::Size resource_size = gfx::Size(10, 10);
  346. scoped_refptr<media::VideoFrame> video_frame =
  347. media::VideoFrame::WrapNativeTextures(
  348. media::PIXEL_FORMAT_ARGB, mailbox_holders, base::DoNothing(),
  349. resource_size, gfx::Rect(10, 10), resource_size, base::TimeDelta());
  350. ASSERT_TRUE(video_frame);
  351. video_frame->metadata().allow_overlay = true;
  352. FakeVideoFrameProvider provider;
  353. provider.set_frame(video_frame);
  354. VideoLayerImpl* video_layer_impl =
  355. impl.AddLayer<VideoLayerImpl>(&provider, media::VIDEO_ROTATION_0);
  356. video_layer_impl->SetBounds(layer_size);
  357. video_layer_impl->SetDrawsContent(true);
  358. video_layer_impl->set_visible_layer_rect(gfx::Rect(layer_size));
  359. CopyProperties(impl.root_layer(), video_layer_impl);
  360. impl.CalcDrawProps(layer_size);
  361. gfx::Rect occluded;
  362. impl.AppendQuadsWithOcclusion(video_layer_impl, occluded);
  363. EXPECT_EQ(1u, impl.quad_list().size());
  364. const viz::DrawQuad* draw_quad = impl.quad_list().ElementAt(0);
  365. ASSERT_EQ(viz::DrawQuad::Material::kTextureContent, draw_quad->material);
  366. const viz::TextureDrawQuad* texture_draw_quad =
  367. viz::TextureDrawQuad::MaterialCast(draw_quad);
  368. EXPECT_EQ(texture_draw_quad->resource_size_in_pixels(), resource_size);
  369. }
  370. } // namespace
  371. } // namespace cc