surface_unittest.cc 58 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571
  1. // Copyright 2015 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 "components/exo/surface.h"
  5. #include "base/bind.h"
  6. #include "base/command_line.h"
  7. #include "base/strings/stringprintf.h"
  8. #include "base/time/time.h"
  9. #include "components/exo/buffer.h"
  10. #include "components/exo/shell_surface.h"
  11. #include "components/exo/sub_surface.h"
  12. #include "components/exo/surface_test_util.h"
  13. #include "components/exo/test/exo_test_base.h"
  14. #include "components/exo/test/exo_test_helper.h"
  15. #include "components/viz/common/quads/compositor_frame.h"
  16. #include "components/viz/common/quads/solid_color_draw_quad.h"
  17. #include "components/viz/common/quads/texture_draw_quad.h"
  18. #include "components/viz/service/surfaces/surface.h"
  19. #include "components/viz/service/surfaces/surface_manager.h"
  20. #include "components/viz/test/begin_frame_args_test.h"
  21. #include "components/viz/test/fake_external_begin_frame_source.h"
  22. #include "testing/gtest/include/gtest/gtest.h"
  23. #include "third_party/khronos/GLES2/gl2.h"
  24. #include "ui/compositor/layer.h"
  25. #include "ui/compositor/layer_tree_owner.h"
  26. #include "ui/display/display.h"
  27. #include "ui/display/display_switches.h"
  28. #include "ui/gfx/geometry/dip_util.h"
  29. #include "ui/gfx/geometry/point_conversions.h"
  30. #include "ui/gfx/geometry/point_f.h"
  31. #include "ui/gfx/geometry/rect.h"
  32. #include "ui/gfx/geometry/rect_conversions.h"
  33. #include "ui/gfx/geometry/size_f.h"
  34. #include "ui/gfx/geometry/test/geometry_util.h"
  35. #include "ui/gfx/gpu_fence.h"
  36. #include "ui/gfx/gpu_fence_handle.h"
  37. #include "ui/gfx/gpu_memory_buffer.h"
  38. #include "ui/wm/core/window_util.h"
  39. namespace exo {
  40. namespace {
  41. std::unique_ptr<std::vector<gfx::Rect>> GetHitTestShapeRects(Surface* surface) {
  42. if (surface->hit_test_region().IsEmpty())
  43. return nullptr;
  44. auto rects = std::make_unique<std::vector<gfx::Rect>>();
  45. for (gfx::Rect rect : surface->hit_test_region())
  46. rects->push_back(rect);
  47. return rects;
  48. }
  49. std::string TransformToString(Transform transform) {
  50. std::string prefix = "Transform::";
  51. std::string name;
  52. switch (transform) {
  53. case Transform::NORMAL:
  54. name = "NORMAL";
  55. break;
  56. case Transform::ROTATE_90:
  57. name = "ROTATE_90";
  58. break;
  59. case Transform::ROTATE_180:
  60. name = "ROTATE_180";
  61. break;
  62. case Transform::ROTATE_270:
  63. name = "ROTATE_270";
  64. break;
  65. case Transform::FLIPPED:
  66. name = "FLIPPED";
  67. break;
  68. case Transform::FLIPPED_ROTATE_90:
  69. name = "FLIPPED_ROTATE_90";
  70. break;
  71. case Transform::FLIPPED_ROTATE_180:
  72. name = "FLIPPED_ROTATE_180";
  73. break;
  74. case Transform::FLIPPED_ROTATE_270:
  75. name = "FLIPPED_ROTATE_270";
  76. break;
  77. default:
  78. return "[UNKNOWN_TRANSFORM]";
  79. }
  80. return prefix + name;
  81. }
  82. class SurfaceTest : public test::ExoTestBase,
  83. public ::testing::WithParamInterface<float> {
  84. public:
  85. SurfaceTest() = default;
  86. SurfaceTest(const SurfaceTest&) = delete;
  87. SurfaceTest& operator=(const SurfaceTest&) = delete;
  88. ~SurfaceTest() override = default;
  89. void SetUp() override {
  90. base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
  91. // Set the device scale factor.
  92. command_line->AppendSwitchASCII(
  93. switches::kForceDeviceScaleFactor,
  94. base::StringPrintf("%f", device_scale_factor()));
  95. test::ExoTestBase::SetUp();
  96. }
  97. void TearDown() override {
  98. test::ExoTestBase::TearDown();
  99. display::Display::ResetForceDeviceScaleFactorForTesting();
  100. }
  101. float device_scale_factor() const { return GetParam(); }
  102. gfx::Rect ToPixel(const gfx::Rect rect) {
  103. return gfx::ToEnclosingRect(
  104. gfx::ConvertRectToPixels(rect, device_scale_factor()));
  105. }
  106. gfx::Rect GetCompleteDamage(const viz::CompositorFrame& frame) {
  107. auto& root_pass = frame.render_pass_list.back();
  108. gfx::Rect complete_damage = root_pass->damage_rect;
  109. for (auto* quad : root_pass->quad_list) {
  110. if (quad->material == viz::DrawQuad::Material::kTextureContent) {
  111. auto* texture_quad = viz::TextureDrawQuad::MaterialCast(quad);
  112. if (texture_quad->damage_rect.has_value()) {
  113. complete_damage.Union(texture_quad->damage_rect.value());
  114. }
  115. }
  116. }
  117. return complete_damage;
  118. }
  119. gfx::Rect ToTargetSpaceDamage(const viz::CompositorFrame& frame) {
  120. // Map a frame's damage back to the coordinate space of its buffer.
  121. return gfx::ScaleToEnclosingRect(GetCompleteDamage(frame),
  122. 1 / device_scale_factor());
  123. }
  124. const viz::CompositorFrame& GetFrameFromSurface(ShellSurface* shell_surface) {
  125. viz::SurfaceId surface_id = shell_surface->host_window()->GetSurfaceId();
  126. const viz::CompositorFrame& frame =
  127. GetSurfaceManager()->GetSurfaceForId(surface_id)->GetActiveFrame();
  128. return frame;
  129. }
  130. void SetBufferTransformHelperTransformAndTest(Surface* surface,
  131. ShellSurface* shell_surface,
  132. Transform transform,
  133. const gfx::Size& expected_size);
  134. void SetCropAndBufferTransformHelperTransformAndTest(
  135. Surface* surface,
  136. ShellSurface* shell_surface,
  137. Transform transform,
  138. const gfx::RectF& expected_rect,
  139. bool has_viewport);
  140. };
  141. void ReleaseBuffer(int* release_buffer_call_count) {
  142. (*release_buffer_call_count)++;
  143. }
  144. void ExplicitReleaseBuffer(int* release_buffer_call_count,
  145. gfx::GpuFenceHandle release_fence) {
  146. (*release_buffer_call_count)++;
  147. }
  148. // Instantiate the Boolean which is used to toggle mouse and touch events in
  149. // the parameterized tests.
  150. INSTANTIATE_TEST_SUITE_P(All, SurfaceTest, testing::Values(1.0f, 1.25f, 2.0f));
  151. TEST_P(SurfaceTest, Attach) {
  152. gfx::Size buffer_size(256, 256);
  153. std::unique_ptr<Buffer> buffer(
  154. new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size)));
  155. // Set the release callback that will be run when buffer is no longer in use.
  156. int release_buffer_call_count = 0;
  157. buffer->set_release_callback(base::BindRepeating(
  158. &ReleaseBuffer, base::Unretained(&release_buffer_call_count)));
  159. std::unique_ptr<Surface> surface(new Surface);
  160. // Attach the buffer to surface1.
  161. surface->Attach(buffer.get());
  162. EXPECT_TRUE(surface->HasPendingAttachedBuffer());
  163. surface->Commit();
  164. EXPECT_EQ(gfx::SizeF(buffer_size), surface->content_size());
  165. // Commit without calling Attach() should have no effect.
  166. surface->Commit();
  167. EXPECT_EQ(0, release_buffer_call_count);
  168. // Attach a null buffer to surface, this should release the previously
  169. // attached buffer.
  170. surface->Attach(nullptr);
  171. EXPECT_FALSE(surface->HasPendingAttachedBuffer());
  172. surface->Commit();
  173. EXPECT_TRUE(surface->content_size().IsEmpty());
  174. // LayerTreeFrameSinkHolder::ReclaimResources() gets called via
  175. // CompositorFrameSinkClient interface. We need to wait here for the mojo
  176. // call to finish so that the release callback finishes running before
  177. // the assertion below.
  178. base::RunLoop().RunUntilIdle();
  179. ASSERT_EQ(1, release_buffer_call_count);
  180. }
  181. TEST_P(SurfaceTest, Damage) {
  182. gfx::Size buffer_size(256, 256);
  183. std::unique_ptr<Buffer> buffer(
  184. new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size)));
  185. std::unique_ptr<Surface> surface(new Surface);
  186. auto shell_surface = std::make_unique<ShellSurface>(surface.get());
  187. // Attach the buffer to the surface. This will update the pending bounds of
  188. // the surface to the buffer size.
  189. surface->Attach(buffer.get());
  190. // Mark areas inside the bounds of the surface as damaged. This should result
  191. // in pending damage.
  192. surface->Damage(gfx::Rect(0, 0, 10, 10));
  193. surface->Damage(gfx::Rect(10, 10, 10, 10));
  194. EXPECT_TRUE(surface->HasPendingDamageForTesting(gfx::Rect(0, 0, 10, 10)));
  195. EXPECT_TRUE(surface->HasPendingDamageForTesting(gfx::Rect(10, 10, 10, 10)));
  196. EXPECT_FALSE(surface->HasPendingDamageForTesting(gfx::Rect(5, 5, 10, 10)));
  197. // Check that damage larger than contents is handled correctly at commit.
  198. surface->Damage(gfx::Rect(gfx::ScaleToCeiledSize(buffer_size, 2.0f)));
  199. surface->Commit();
  200. base::RunLoop().RunUntilIdle();
  201. {
  202. const viz::CompositorFrame& frame =
  203. GetFrameFromSurface(shell_surface.get());
  204. EXPECT_EQ(ToPixel(gfx::Rect(buffer_size)), GetCompleteDamage(frame));
  205. }
  206. gfx::RectF buffer_damage(32, 64, 16, 32);
  207. gfx::Rect surface_damage = gfx::ToNearestRect(buffer_damage);
  208. // Check that damage is correct for a non-square rectangle not at the origin.
  209. surface->Damage(surface_damage);
  210. surface->Commit();
  211. base::RunLoop().RunUntilIdle();
  212. // Adjust damage for DSF filtering and verify it below.
  213. if (device_scale_factor() > 1.f)
  214. buffer_damage.Inset(-1.f);
  215. {
  216. const viz::CompositorFrame& frame =
  217. GetFrameFromSurface(shell_surface.get());
  218. EXPECT_TRUE(
  219. ToTargetSpaceDamage(frame).Contains(gfx::ToNearestRect(buffer_damage)));
  220. }
  221. }
  222. TEST_P(SurfaceTest, SubsurfaceDamageAggregation) {
  223. gfx::Size buffer_size(256, 512);
  224. auto buffer = std::make_unique<Buffer>(
  225. exo_test_helper()->CreateGpuMemoryBuffer(buffer_size));
  226. auto surface = std::make_unique<Surface>();
  227. auto shell_surface = std::make_unique<ShellSurface>(surface.get());
  228. surface->Attach(buffer.get());
  229. gfx::Size child_buffer_size(64, 128);
  230. auto child_buffer = std::make_unique<Buffer>(
  231. exo_test_helper()->CreateGpuMemoryBuffer(child_buffer_size));
  232. auto child_surface = std::make_unique<Surface>();
  233. auto sub_surface =
  234. std::make_unique<SubSurface>(child_surface.get(), surface.get());
  235. child_surface->Attach(child_buffer.get());
  236. child_surface->Commit();
  237. surface->Commit();
  238. base::RunLoop().RunUntilIdle();
  239. {
  240. // Initial frame has full damage.
  241. const viz::CompositorFrame& frame =
  242. GetFrameFromSurface(shell_surface.get());
  243. const gfx::Rect scaled_damage = gfx::ToNearestRect(gfx::ScaleRect(
  244. gfx::RectF(gfx::Rect(buffer_size)), device_scale_factor()));
  245. EXPECT_EQ(scaled_damage, GetCompleteDamage(frame));
  246. }
  247. const gfx::RectF surface_damage(16, 16);
  248. const gfx::RectF subsurface_damage(32, 32, 16, 16);
  249. int margin = ceil(device_scale_factor());
  250. child_surface->Damage(gfx::ToNearestRect(subsurface_damage));
  251. child_surface->Commit();
  252. surface->Commit();
  253. base::RunLoop().RunUntilIdle();
  254. {
  255. // Subsurface damage should be propagated.
  256. const viz::CompositorFrame& frame =
  257. GetFrameFromSurface(shell_surface.get());
  258. const gfx::Rect scaled_damage = gfx::ToNearestRect(
  259. gfx::ScaleRect(subsurface_damage, device_scale_factor()));
  260. EXPECT_TRUE(
  261. scaled_damage.ApproximatelyEqual(GetCompleteDamage(frame), margin));
  262. }
  263. surface->Damage(gfx::ToNearestRect(surface_damage));
  264. surface->Commit();
  265. base::RunLoop().RunUntilIdle();
  266. {
  267. // When commit is called on the root with no call on the child, the damage
  268. // from the previous frame shouldn't persist.
  269. const viz::CompositorFrame& frame =
  270. GetFrameFromSurface(shell_surface.get());
  271. const gfx::Rect scaled_damage = gfx::ToNearestRect(
  272. gfx::ScaleRect(surface_damage, device_scale_factor()));
  273. EXPECT_TRUE(
  274. scaled_damage.ApproximatelyEqual(GetCompleteDamage(frame), margin));
  275. }
  276. }
  277. TEST_P(SurfaceTest, SubsurfaceDamageSynchronizedCommitBehavior) {
  278. gfx::Size buffer_size(256, 512);
  279. auto buffer = std::make_unique<Buffer>(
  280. exo_test_helper()->CreateGpuMemoryBuffer(buffer_size));
  281. auto surface = std::make_unique<Surface>();
  282. auto shell_surface = std::make_unique<ShellSurface>(surface.get());
  283. surface->Attach(buffer.get());
  284. gfx::Size child_buffer_size(64, 128);
  285. auto child_buffer = std::make_unique<Buffer>(
  286. exo_test_helper()->CreateGpuMemoryBuffer(child_buffer_size));
  287. auto child_surface = std::make_unique<Surface>();
  288. auto sub_surface =
  289. std::make_unique<SubSurface>(child_surface.get(), surface.get());
  290. // Set commit behavior to synchronized.
  291. sub_surface->SetCommitBehavior(true);
  292. child_surface->Attach(child_buffer.get());
  293. child_surface->Commit();
  294. surface->Commit();
  295. base::RunLoop().RunUntilIdle();
  296. {
  297. // Initial frame has full damage.
  298. const viz::CompositorFrame& frame =
  299. GetFrameFromSurface(shell_surface.get());
  300. const gfx::Rect scaled_damage = gfx::ToNearestRect(gfx::ScaleRect(
  301. gfx::RectF(gfx::Rect(buffer_size)), device_scale_factor()));
  302. EXPECT_EQ(scaled_damage, GetCompleteDamage(frame));
  303. }
  304. const gfx::RectF subsurface_damage(32, 32, 16, 16);
  305. const gfx::RectF subsurface_damage2(0, 0, 16, 16);
  306. int margin = ceil(device_scale_factor());
  307. child_surface->Damage(gfx::ToNearestRect(subsurface_damage));
  308. EXPECT_TRUE(child_surface->HasPendingDamageForTesting(
  309. gfx::ToNearestRect(subsurface_damage)));
  310. // Subsurface damage is cached.
  311. child_surface->Commit();
  312. EXPECT_FALSE(child_surface->HasPendingDamageForTesting(
  313. gfx::ToNearestRect(subsurface_damage)));
  314. base::RunLoop().RunUntilIdle();
  315. {
  316. // Subsurface damage should not be propagated at all.
  317. const viz::CompositorFrame& frame =
  318. GetFrameFromSurface(shell_surface.get());
  319. const gfx::Rect scaled_damage = gfx::ToNearestRect(gfx::ScaleRect(
  320. gfx::RectF(gfx::Rect(buffer_size)), device_scale_factor()));
  321. EXPECT_EQ(scaled_damage, GetCompleteDamage(frame));
  322. }
  323. // Damage but do not commit.
  324. child_surface->Damage(gfx::ToNearestRect(subsurface_damage2));
  325. EXPECT_TRUE(child_surface->HasPendingDamageForTesting(
  326. gfx::ToNearestRect(subsurface_damage2)));
  327. // Apply subsurface damage from cached state, not pending state.
  328. surface->Commit();
  329. base::RunLoop().RunUntilIdle();
  330. {
  331. // Subsurface damage in cached state should be propagated.
  332. const viz::CompositorFrame& frame =
  333. GetFrameFromSurface(shell_surface.get());
  334. const gfx::Rect scaled_damage = gfx::ToNearestRect(
  335. gfx::ScaleRect(subsurface_damage, device_scale_factor()));
  336. EXPECT_TRUE(
  337. scaled_damage.ApproximatelyEqual(GetCompleteDamage(frame), margin));
  338. }
  339. }
  340. TEST_P(SurfaceTest, SubsurfaceDamageDesynchronizedCommitBehavior) {
  341. gfx::Size buffer_size(256, 512);
  342. auto buffer = std::make_unique<Buffer>(
  343. exo_test_helper()->CreateGpuMemoryBuffer(buffer_size));
  344. auto surface = std::make_unique<Surface>();
  345. auto shell_surface = std::make_unique<ShellSurface>(surface.get());
  346. surface->Attach(buffer.get());
  347. gfx::Size child_buffer_size(64, 128);
  348. auto child_buffer = std::make_unique<Buffer>(
  349. exo_test_helper()->CreateGpuMemoryBuffer(child_buffer_size));
  350. auto child_surface = std::make_unique<Surface>();
  351. auto sub_surface =
  352. std::make_unique<SubSurface>(child_surface.get(), surface.get());
  353. // Set commit behavior to desynchronized.
  354. sub_surface->SetCommitBehavior(false);
  355. child_surface->Attach(child_buffer.get());
  356. child_surface->Commit();
  357. surface->Commit();
  358. base::RunLoop().RunUntilIdle();
  359. {
  360. // Initial frame has full damage.
  361. const viz::CompositorFrame& frame =
  362. GetFrameFromSurface(shell_surface.get());
  363. const gfx::Rect scaled_damage = gfx::ToNearestRect(gfx::ScaleRect(
  364. gfx::RectF(gfx::Rect(buffer_size)), device_scale_factor()));
  365. EXPECT_EQ(scaled_damage, GetCompleteDamage(frame));
  366. }
  367. const gfx::RectF subsurface_damage(32, 32, 16, 16);
  368. int margin = ceil(device_scale_factor());
  369. child_surface->Damage(gfx::ToNearestRect(subsurface_damage));
  370. EXPECT_TRUE(child_surface->HasPendingDamageForTesting(
  371. gfx::ToNearestRect(subsurface_damage)));
  372. // Subsurface damage is applied.
  373. child_surface->Commit();
  374. EXPECT_FALSE(child_surface->HasPendingDamageForTesting(
  375. gfx::ToNearestRect(subsurface_damage)));
  376. base::RunLoop().RunUntilIdle();
  377. {
  378. // Subsurface damage should be propagated.
  379. const viz::CompositorFrame& frame =
  380. GetFrameFromSurface(shell_surface.get());
  381. const gfx::Rect scaled_damage = gfx::ToNearestRect(
  382. gfx::ScaleRect(subsurface_damage, device_scale_factor()));
  383. EXPECT_TRUE(
  384. scaled_damage.ApproximatelyEqual(GetCompleteDamage(frame), margin));
  385. }
  386. }
  387. void SetFrameTime(base::TimeTicks* result, base::TimeTicks frame_time) {
  388. *result = frame_time;
  389. }
  390. TEST_P(SurfaceTest, RequestFrameCallback) {
  391. // Must be before surface so it outlives it, for surface's destructor calls
  392. // SetFrameTime() referencing this.
  393. base::TimeTicks frame_time;
  394. std::unique_ptr<Surface> surface(new Surface);
  395. surface->RequestFrameCallback(
  396. base::BindRepeating(&SetFrameTime, base::Unretained(&frame_time)));
  397. surface->Commit();
  398. // Callback should not run synchronously.
  399. EXPECT_TRUE(frame_time.is_null());
  400. }
  401. // Disabled due to flakiness: crbug.com/856145
  402. #if defined(LEAK_SANITIZER)
  403. #define MAYBE_SetOpaqueRegion DISABLED_SetOpaqueRegion
  404. #else
  405. #define MAYBE_SetOpaqueRegion SetOpaqueRegion
  406. #endif
  407. TEST_P(SurfaceTest, MAYBE_SetOpaqueRegion) {
  408. gfx::Size buffer_size(1, 1);
  409. auto buffer = std::make_unique<Buffer>(
  410. exo_test_helper()->CreateGpuMemoryBuffer(buffer_size));
  411. auto surface = std::make_unique<Surface>();
  412. auto shell_surface = std::make_unique<ShellSurface>(surface.get());
  413. // Attaching a buffer with alpha channel.
  414. surface->Attach(buffer.get());
  415. // Setting an opaque region that contains the buffer size doesn't require
  416. // draw with blending.
  417. surface->SetOpaqueRegion(gfx::Rect(256, 256));
  418. surface->Commit();
  419. base::RunLoop().RunUntilIdle();
  420. {
  421. const viz::CompositorFrame& frame =
  422. GetFrameFromSurface(shell_surface.get());
  423. ASSERT_EQ(1u, frame.render_pass_list.size());
  424. ASSERT_EQ(1u, frame.render_pass_list.back()->quad_list.size());
  425. auto* texture_draw_quad = viz::TextureDrawQuad::MaterialCast(
  426. frame.render_pass_list.back()->quad_list.back());
  427. EXPECT_FALSE(texture_draw_quad->ShouldDrawWithBlending());
  428. EXPECT_EQ(SkColors::kBlack, texture_draw_quad->background_color);
  429. EXPECT_EQ(gfx::Rect(buffer_size), ToTargetSpaceDamage(frame));
  430. }
  431. // Setting an empty opaque region requires draw with blending.
  432. surface->SetOpaqueRegion(gfx::Rect());
  433. surface->Commit();
  434. base::RunLoop().RunUntilIdle();
  435. {
  436. const viz::CompositorFrame& frame =
  437. GetFrameFromSurface(shell_surface.get());
  438. ASSERT_EQ(1u, frame.render_pass_list.size());
  439. ASSERT_EQ(1u, frame.render_pass_list.back()->quad_list.size());
  440. auto* texture_draw_quad = viz::TextureDrawQuad::MaterialCast(
  441. frame.render_pass_list.back()->quad_list.back());
  442. EXPECT_TRUE(texture_draw_quad->ShouldDrawWithBlending());
  443. EXPECT_EQ(SkColors::kTransparent, texture_draw_quad->background_color);
  444. EXPECT_EQ(gfx::Rect(buffer_size), ToTargetSpaceDamage(frame));
  445. }
  446. std::unique_ptr<Buffer> buffer_without_alpha(
  447. new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(
  448. buffer_size, gfx::BufferFormat::RGBX_8888)));
  449. // Attaching a buffer without an alpha channel doesn't require draw with
  450. // blending.
  451. surface->Attach(buffer_without_alpha.get());
  452. surface->Commit();
  453. base::RunLoop().RunUntilIdle();
  454. {
  455. const viz::CompositorFrame& frame =
  456. GetFrameFromSurface(shell_surface.get());
  457. ASSERT_EQ(1u, frame.render_pass_list.size());
  458. ASSERT_EQ(1u, frame.render_pass_list.back()->quad_list.size());
  459. EXPECT_FALSE(frame.render_pass_list.back()
  460. ->quad_list.back()
  461. ->ShouldDrawWithBlending());
  462. EXPECT_EQ(ToPixel(gfx::Rect(0, 0, 0, 0)), GetCompleteDamage(frame));
  463. }
  464. }
  465. TEST_P(SurfaceTest, SetInputRegion) {
  466. // Create a shell surface which size is 512x512.
  467. auto surface = std::make_unique<Surface>();
  468. auto shell_surface = std::make_unique<ShellSurface>(surface.get());
  469. gfx::Size buffer_size(512, 512);
  470. auto buffer = std::make_unique<Buffer>(
  471. exo_test_helper()->CreateGpuMemoryBuffer(buffer_size));
  472. surface->Attach(buffer.get());
  473. surface->Commit();
  474. {
  475. // Default input region should match surface bounds.
  476. auto rects = GetHitTestShapeRects(surface.get());
  477. ASSERT_TRUE(rects);
  478. ASSERT_EQ(1u, rects->size());
  479. ASSERT_EQ(gfx::Rect(512, 512), (*rects)[0]);
  480. }
  481. {
  482. // Setting a non-empty input region should succeed.
  483. surface->SetInputRegion(gfx::Rect(256, 256));
  484. surface->Commit();
  485. auto rects = GetHitTestShapeRects(surface.get());
  486. ASSERT_TRUE(rects);
  487. ASSERT_EQ(1u, rects->size());
  488. ASSERT_EQ(gfx::Rect(256, 256), (*rects)[0]);
  489. }
  490. {
  491. // Setting an empty input region should succeed.
  492. surface->SetInputRegion(gfx::Rect());
  493. surface->Commit();
  494. EXPECT_FALSE(GetHitTestShapeRects(surface.get()));
  495. }
  496. {
  497. cc::Region region = gfx::Rect(512, 512);
  498. region.Subtract(gfx::Rect(0, 64, 64, 64));
  499. region.Subtract(gfx::Rect(88, 88, 12, 55));
  500. region.Subtract(gfx::Rect(100, 0, 33, 66));
  501. // Setting a non-rectangle input region should succeed.
  502. surface->SetInputRegion(region);
  503. surface->Commit();
  504. auto rects = GetHitTestShapeRects(surface.get());
  505. ASSERT_TRUE(rects);
  506. ASSERT_EQ(10u, rects->size());
  507. cc::Region result;
  508. for (const auto& r : *rects)
  509. result.Union(r);
  510. ASSERT_EQ(result, region);
  511. }
  512. {
  513. // Input region should be clipped to surface bounds.
  514. surface->SetInputRegion(gfx::Rect(-50, -50, 1000, 100));
  515. surface->Commit();
  516. auto rects = GetHitTestShapeRects(surface.get());
  517. ASSERT_TRUE(rects);
  518. ASSERT_EQ(1u, rects->size());
  519. ASSERT_EQ(gfx::Rect(512, 50), (*rects)[0]);
  520. }
  521. {
  522. // Hit test region should accumulate input regions of sub-surfaces.
  523. gfx::Rect input_rect(50, 50, 100, 100);
  524. surface->SetInputRegion(input_rect);
  525. gfx::Rect child_input_rect(-50, -50, 1000, 100);
  526. auto child_buffer = std::make_unique<Buffer>(
  527. exo_test_helper()->CreateGpuMemoryBuffer(child_input_rect.size()));
  528. auto child_surface = std::make_unique<Surface>();
  529. auto sub_surface =
  530. std::make_unique<SubSurface>(child_surface.get(), surface.get());
  531. sub_surface->SetPosition(gfx::PointF(child_input_rect.origin()));
  532. child_surface->Attach(child_buffer.get());
  533. child_surface->Commit();
  534. surface->Commit();
  535. auto rects = GetHitTestShapeRects(surface.get());
  536. ASSERT_TRUE(rects);
  537. ASSERT_EQ(2u, rects->size());
  538. cc::Region result = cc::UnionRegions((*rects)[0], (*rects)[1]);
  539. ASSERT_EQ(cc::UnionRegions(input_rect, child_input_rect), result);
  540. }
  541. }
  542. TEST_P(SurfaceTest, SetBufferScale) {
  543. gfx::Size buffer_size(512, 512);
  544. auto buffer = std::make_unique<Buffer>(
  545. exo_test_helper()->CreateGpuMemoryBuffer(buffer_size));
  546. auto surface = std::make_unique<Surface>();
  547. auto shell_surface = std::make_unique<ShellSurface>(surface.get());
  548. // This will update the bounds of the surface and take the buffer scale into
  549. // account.
  550. const float kBufferScale = 2.0f;
  551. surface->Attach(buffer.get());
  552. surface->SetBufferScale(kBufferScale);
  553. surface->Commit();
  554. EXPECT_EQ(
  555. gfx::ScaleToFlooredSize(buffer_size, 1.0f / kBufferScale).ToString(),
  556. surface->window()->bounds().size().ToString());
  557. gfx::SizeF buffer_size_float = gfx::SizeF(buffer_size);
  558. buffer_size_float.Scale(1.0f / kBufferScale);
  559. EXPECT_EQ(buffer_size_float.ToString(), surface->content_size().ToString());
  560. base::RunLoop().RunUntilIdle();
  561. const viz::CompositorFrame& frame = GetFrameFromSurface(shell_surface.get());
  562. ASSERT_EQ(1u, frame.render_pass_list.size());
  563. EXPECT_EQ(ToPixel(gfx::Rect(0, 0, 256, 256)), GetCompleteDamage(frame));
  564. }
  565. void SurfaceTest::SetBufferTransformHelperTransformAndTest(
  566. Surface* surface,
  567. ShellSurface* shell_surface,
  568. Transform transform,
  569. const gfx::Size& expected_size) {
  570. std::stringstream scoped_trace_message;
  571. scoped_trace_message << "SetBufferTransformHelperTransformAndTest("
  572. << "transform=" << TransformToString(transform) << ")";
  573. SCOPED_TRACE(scoped_trace_message.str());
  574. surface->SetBufferTransform(transform);
  575. surface->Commit();
  576. EXPECT_EQ(gfx::Size(expected_size.width(), expected_size.height()),
  577. surface->window()->bounds().size());
  578. EXPECT_EQ(gfx::SizeF(expected_size.width(), expected_size.height()),
  579. surface->content_size());
  580. base::RunLoop().RunUntilIdle();
  581. {
  582. const viz::CompositorFrame& frame = GetFrameFromSurface(shell_surface);
  583. ASSERT_EQ(1u, frame.render_pass_list.size());
  584. EXPECT_EQ(
  585. ToPixel(gfx::Rect(0, 0, expected_size.width(), expected_size.height())),
  586. GetCompleteDamage(frame));
  587. const auto& quad_list = frame.render_pass_list[0]->quad_list;
  588. ASSERT_EQ(1u, quad_list.size());
  589. EXPECT_EQ(
  590. ToPixel(gfx::Rect(0, 0, 512, 256)),
  591. cc::MathUtil::MapEnclosingClippedRect(
  592. quad_list.front()->shared_quad_state->quad_to_target_transform,
  593. quad_list.front()->rect));
  594. }
  595. }
  596. // Disabled due to flakiness: crbug.com/856145
  597. #if defined(LEAK_SANITIZER)
  598. #define MAYBE_SetBufferTransform DISABLED_SetBufferTransform
  599. #else
  600. #define MAYBE_SetBufferTransform SetBufferTransform
  601. #endif
  602. TEST_P(SurfaceTest, MAYBE_SetBufferTransform) {
  603. gfx::Size buffer_size(256, 512);
  604. auto buffer = std::make_unique<Buffer>(
  605. exo_test_helper()->CreateGpuMemoryBuffer(buffer_size));
  606. auto surface = std::make_unique<Surface>();
  607. auto shell_surface = std::make_unique<ShellSurface>(surface.get());
  608. // This will update the bounds of the surface and take the buffer transform
  609. // into account.
  610. surface->Attach(buffer.get());
  611. gfx::Size inverted_size(buffer_size.height(), buffer_size.width());
  612. SetBufferTransformHelperTransformAndTest(surface.get(), shell_surface.get(),
  613. Transform::ROTATE_90, inverted_size);
  614. SetBufferTransformHelperTransformAndTest(surface.get(), shell_surface.get(),
  615. Transform::FLIPPED_ROTATE_90,
  616. inverted_size);
  617. gfx::Size child_buffer_size(64, 128);
  618. auto child_buffer = std::make_unique<Buffer>(
  619. exo_test_helper()->CreateGpuMemoryBuffer(child_buffer_size));
  620. auto child_surface = std::make_unique<Surface>();
  621. auto sub_surface =
  622. std::make_unique<SubSurface>(child_surface.get(), surface.get());
  623. // Set position to 20, 10.
  624. gfx::PointF child_position(20, 10);
  625. sub_surface->SetPosition(child_position);
  626. child_surface->Attach(child_buffer.get());
  627. child_surface->SetBufferTransform(Transform::ROTATE_180);
  628. const int kChildBufferScale = 2;
  629. child_surface->SetBufferScale(kChildBufferScale);
  630. child_surface->Commit();
  631. surface->Commit();
  632. EXPECT_EQ(
  633. gfx::ScaleToRoundedSize(child_buffer_size, 1.0f / kChildBufferScale),
  634. child_surface->window()->bounds().size());
  635. EXPECT_EQ(
  636. gfx::ScaleToRoundedSize(child_buffer_size, 1.0f / kChildBufferScale),
  637. gfx::ToRoundedSize(child_surface->content_size()));
  638. base::RunLoop().RunUntilIdle();
  639. {
  640. const viz::CompositorFrame& frame =
  641. GetFrameFromSurface(shell_surface.get());
  642. ASSERT_EQ(1u, frame.render_pass_list.size());
  643. const auto& quad_list = frame.render_pass_list[0]->quad_list;
  644. ASSERT_EQ(2u, quad_list.size());
  645. EXPECT_EQ(
  646. ToPixel(gfx::Rect(gfx::ToRoundedPoint(child_position),
  647. gfx::ScaleToRoundedSize(child_buffer_size,
  648. 1.0f / kChildBufferScale))),
  649. cc::MathUtil::MapEnclosingClippedRect(
  650. quad_list.front()->shared_quad_state->quad_to_target_transform,
  651. quad_list.front()->rect));
  652. }
  653. }
  654. TEST_P(SurfaceTest, MirrorLayers) {
  655. gfx::Size buffer_size(512, 512);
  656. auto buffer = std::make_unique<Buffer>(
  657. exo_test_helper()->CreateGpuMemoryBuffer(buffer_size));
  658. auto surface = std::make_unique<Surface>();
  659. auto shell_surface = std::make_unique<ShellSurface>(surface.get());
  660. surface->Attach(buffer.get());
  661. surface->Commit();
  662. base::RunLoop().RunUntilIdle();
  663. EXPECT_EQ(buffer_size, surface->window()->bounds().size());
  664. EXPECT_EQ(buffer_size, surface->window()->layer()->bounds().size());
  665. std::unique_ptr<ui::LayerTreeOwner> old_layer_owner =
  666. ::wm::MirrorLayers(shell_surface->host_window(), false /* sync_bounds */);
  667. EXPECT_EQ(buffer_size, surface->window()->bounds().size());
  668. EXPECT_EQ(buffer_size, surface->window()->layer()->bounds().size());
  669. EXPECT_EQ(buffer_size, old_layer_owner->root()->bounds().size());
  670. EXPECT_TRUE(shell_surface->host_window()->layer()->has_external_content());
  671. EXPECT_TRUE(old_layer_owner->root()->has_external_content());
  672. }
  673. TEST_P(SurfaceTest, SetViewport) {
  674. gfx::Size buffer_size(1, 1);
  675. auto buffer = std::make_unique<Buffer>(
  676. exo_test_helper()->CreateGpuMemoryBuffer(buffer_size));
  677. auto surface = std::make_unique<Surface>();
  678. auto shell_surface = std::make_unique<ShellSurface>(surface.get());
  679. // This will update the bounds of the surface and take the viewport into
  680. // account.
  681. surface->Attach(buffer.get());
  682. gfx::SizeF viewport(256, 256);
  683. surface->SetViewport(viewport);
  684. surface->Commit();
  685. EXPECT_EQ(viewport.ToString(), surface->content_size().ToString());
  686. // This will update the bounds of the surface and take the viewport2 into
  687. // account.
  688. gfx::SizeF viewport2(512, 512);
  689. surface->SetViewport(viewport2);
  690. surface->Commit();
  691. EXPECT_EQ(viewport2.ToString(),
  692. gfx::SizeF(surface->window()->bounds().size()).ToString());
  693. EXPECT_EQ(viewport2.ToString(), surface->content_size().ToString());
  694. base::RunLoop().RunUntilIdle();
  695. const viz::CompositorFrame& frame = GetFrameFromSurface(shell_surface.get());
  696. ASSERT_EQ(1u, frame.render_pass_list.size());
  697. EXPECT_EQ(ToPixel(gfx::Rect(0, 0, 512, 512)), GetCompleteDamage(frame));
  698. // This will make the surface have no content regardless of the viewport.
  699. surface->Attach(nullptr);
  700. surface->Commit();
  701. EXPECT_TRUE(surface->content_size().IsEmpty());
  702. }
  703. TEST_P(SurfaceTest, SubpixelCoordinate) {
  704. gfx::Size buffer_size(512, 512);
  705. auto buffer = std::make_unique<Buffer>(
  706. exo_test_helper()->CreateGpuMemoryBuffer(buffer_size));
  707. auto surface = std::make_unique<Surface>();
  708. auto shell_surface = std::make_unique<ShellSurface>(surface.get());
  709. // This will update the bounds of the surface and take the buffer transform
  710. // into account.
  711. surface->Attach(buffer.get());
  712. gfx::Size inverted_size(buffer_size.height(), buffer_size.width());
  713. gfx::Size child_buffer_size(64, 64);
  714. auto child_buffer = std::make_unique<Buffer>(
  715. exo_test_helper()->CreateGpuMemoryBuffer(child_buffer_size));
  716. auto child_surface = std::make_unique<Surface>();
  717. auto sub_surface =
  718. std::make_unique<SubSurface>(child_surface.get(), surface.get());
  719. gfx::Transform device_scale_transform;
  720. device_scale_transform.Scale(1.f / device_scale_factor(),
  721. 1.f / device_scale_factor());
  722. child_surface->Attach(child_buffer.get());
  723. // These rects are in pixel coordinates with some having subpixel coordinates.
  724. gfx::RectF kTestRects[] = {
  725. gfx::RectF(10, 20, 30, 40), gfx::RectF(11, 22, 33, 44),
  726. gfx::RectF(10.5, 20, 30, 40), gfx::RectF(10, 20.5, 30, 40),
  727. gfx::RectF(10, 20, 30.5, 40), gfx::RectF(10, 20, 30, 40.5),
  728. gfx::RectF(10.5, 20, 30, 40.5), gfx::RectF(10.5, 20.5, 30, 40)};
  729. bool kExpectedAligned[] = {true, true, false, false,
  730. false, false, false, false};
  731. static_assert(std::size(kTestRects) == std::size(kExpectedAligned),
  732. "Number of elements in each list should be the identical.");
  733. for (int j = 0; j < 2; j++) {
  734. const bool kTestCaseRotation = (j == 1);
  735. for (size_t i = 0; i < std::size(kTestRects); i++) {
  736. auto rect_in_dip = kTestRects[i];
  737. device_scale_transform.TransformRect(&rect_in_dip);
  738. sub_surface->SetPosition(rect_in_dip.origin());
  739. child_surface->SetViewport(rect_in_dip.size());
  740. const int kChildBufferScale = 2;
  741. child_surface->SetBufferScale(kChildBufferScale);
  742. if (kTestCaseRotation) {
  743. child_surface->SetBufferTransform(Transform::ROTATE_90);
  744. }
  745. child_surface->Commit();
  746. surface->Commit();
  747. base::RunLoop().RunUntilIdle();
  748. const viz::CompositorFrame& frame =
  749. GetFrameFromSurface(shell_surface.get());
  750. ASSERT_EQ(1u, frame.render_pass_list.size());
  751. const auto& quad_list = frame.render_pass_list[0]->quad_list;
  752. ASSERT_EQ(2u, quad_list.size());
  753. auto transform =
  754. quad_list.front()->shared_quad_state->quad_to_target_transform;
  755. auto rect = gfx::RectF(quad_list.front()->rect);
  756. transform.TransformRect(&rect);
  757. if (kExpectedAligned[i] && !kTestCaseRotation) {
  758. // A transformed rect cannot express a rotation.
  759. // Manipulation of texture coordinates, in addition to a transformed
  760. // rect, can represent flip/mirror but only as two uv points and not as
  761. // a uv rect.
  762. auto* tex_draw_quad =
  763. viz::TextureDrawQuad::MaterialCast(quad_list.front());
  764. EXPECT_POINTF_NEAR(tex_draw_quad->uv_top_left, gfx::PointF(0, 0),
  765. 0.001f);
  766. EXPECT_POINTF_NEAR(tex_draw_quad->uv_bottom_right, gfx::PointF(1, 1),
  767. 0.001f);
  768. EXPECT_EQ(gfx::Transform(), transform);
  769. EXPECT_EQ(kTestRects[i], rect);
  770. } else {
  771. EXPECT_EQ(gfx::Rect(1, 1), quad_list.front()->rect);
  772. // Subpixel quads have non identity transforms and due to floating point
  773. // math can only be approximately compared.
  774. EXPECT_NEAR(kTestRects[i].x(), rect.x(), 0.001f);
  775. EXPECT_NEAR(kTestRects[i].y(), rect.y(), 0.001f);
  776. EXPECT_NEAR(kTestRects[i].width(), rect.width(), 0.001f);
  777. EXPECT_NEAR(kTestRects[i].height(), rect.height(), 0.001f);
  778. }
  779. }
  780. }
  781. }
  782. TEST_P(SurfaceTest, SetCrop) {
  783. gfx::Size buffer_size(16, 16);
  784. auto buffer = std::make_unique<Buffer>(
  785. exo_test_helper()->CreateGpuMemoryBuffer(buffer_size));
  786. auto surface = std::make_unique<Surface>();
  787. auto shell_surface = std::make_unique<ShellSurface>(surface.get());
  788. surface->Attach(buffer.get());
  789. gfx::Size crop_size(12, 12);
  790. surface->SetCrop(gfx::RectF(gfx::PointF(2.0, 2.0), gfx::SizeF(crop_size)));
  791. surface->Commit();
  792. EXPECT_EQ(crop_size.ToString(),
  793. surface->window()->bounds().size().ToString());
  794. EXPECT_EQ(gfx::SizeF(crop_size).ToString(),
  795. surface->content_size().ToString());
  796. base::RunLoop().RunUntilIdle();
  797. const viz::CompositorFrame& frame = GetFrameFromSurface(shell_surface.get());
  798. ASSERT_EQ(1u, frame.render_pass_list.size());
  799. EXPECT_EQ(ToPixel(gfx::Rect(0, 0, 12, 12)), GetCompleteDamage(frame));
  800. // This will make the surface have no content regardless of the crop.
  801. surface->Attach(nullptr);
  802. surface->Commit();
  803. EXPECT_TRUE(surface->content_size().IsEmpty());
  804. }
  805. void SurfaceTest::SetCropAndBufferTransformHelperTransformAndTest(
  806. Surface* surface,
  807. ShellSurface* shell_surface,
  808. Transform transform,
  809. const gfx::RectF& expected_rect,
  810. bool has_viewport) {
  811. const gfx::Rect target_with_no_viewport(ToPixel(gfx::Rect(gfx::Size(52, 4))));
  812. const gfx::Rect target_with_viewport(ToPixel(gfx::Rect(gfx::Size(128, 64))));
  813. std::stringstream scoped_trace_message;
  814. scoped_trace_message << "SetCropAndBufferTransformHelperTransformAndTest("
  815. << "transform=" << TransformToString(transform)
  816. << ", has_viewport="
  817. << ((has_viewport) ? "true" : "false") << ")";
  818. SCOPED_TRACE(scoped_trace_message.str());
  819. surface->SetBufferTransform(transform);
  820. surface->Commit();
  821. base::RunLoop().RunUntilIdle();
  822. {
  823. const viz::CompositorFrame& frame = GetFrameFromSurface(shell_surface);
  824. ASSERT_EQ(1u, frame.render_pass_list.size());
  825. const viz::QuadList& quad_list = frame.render_pass_list[0]->quad_list;
  826. ASSERT_EQ(1u, quad_list.size());
  827. const viz::TextureDrawQuad* quad =
  828. viz::TextureDrawQuad::MaterialCast(quad_list.front());
  829. EXPECT_EQ(expected_rect.origin(), quad->uv_top_left);
  830. EXPECT_EQ(expected_rect.bottom_right(), quad->uv_bottom_right);
  831. EXPECT_EQ(
  832. (has_viewport) ? target_with_viewport : target_with_no_viewport,
  833. cc::MathUtil::MapEnclosingClippedRect(
  834. quad->shared_quad_state->quad_to_target_transform, quad->rect));
  835. }
  836. }
  837. // Disabled due to flakiness: crbug.com/856145
  838. #if defined(LEAK_SANITIZER)
  839. #define MAYBE_SetCropAndBufferTransform DISABLED_SetCropAndBufferTransform
  840. #else
  841. #define MAYBE_SetCropAndBufferTransform SetCropAndBufferTransform
  842. #endif
  843. TEST_P(SurfaceTest, MAYBE_SetCropAndBufferTransform) {
  844. gfx::Size buffer_size(128, 64);
  845. auto buffer = std::make_unique<Buffer>(
  846. exo_test_helper()->CreateGpuMemoryBuffer(buffer_size));
  847. auto surface = std::make_unique<Surface>();
  848. auto shell_surface = std::make_unique<ShellSurface>(surface.get());
  849. surface->Attach(buffer.get());
  850. gfx::Size crop_size(52, 4);
  851. gfx::Point crop_origin(4, 12);
  852. gfx::Rect crop_rect(crop_origin, crop_size);
  853. // These rects represent the left, right, top, bottom values of the crop rect
  854. // normalized from the buffer size for each transformation.
  855. static constexpr SkRect crop_0 =
  856. SkRect::MakeLTRB(0.03125f, 0.1875f, 0.4375f, 0.25f);
  857. static constexpr SkRect crop_90 =
  858. SkRect::MakeLTRB(0.875f, 0.0625f, 0.90625f, 0.875f);
  859. static constexpr SkRect crop_180 =
  860. SkRect::MakeLTRB(0.5625f, 0.75f, 0.96875f, 0.8125f);
  861. static constexpr SkRect crop_270 =
  862. SkRect::MakeLTRB(0.09375f, 0.125f, 0.125f, 0.9375f);
  863. static constexpr SkRect flipped_crop_0 =
  864. SkRect::MakeLTRB(0.5625f, 0.1875f, 0.96875f, 0.25f);
  865. static constexpr SkRect flipped_crop_90 =
  866. SkRect::MakeLTRB(0.09375f, 0.0625f, 0.125f, 0.875f);
  867. static constexpr SkRect flipped_crop_180 =
  868. SkRect::MakeLTRB(0.03125f, 0.75f, 0.4375f, 0.8125f);
  869. static constexpr SkRect flipped_crop_270 =
  870. SkRect::MakeLTRB(0.875f, 0.125f, 0.90625f, 0.9375f);
  871. surface->SetCrop(gfx::RectF(gfx::PointF(crop_origin), gfx::SizeF(crop_size)));
  872. struct TransformTestcase {
  873. Transform transform;
  874. const SkRect& expected_rect;
  875. constexpr TransformTestcase(Transform transform_in,
  876. const SkRect& expected_rect_in)
  877. : transform(transform_in), expected_rect(expected_rect_in) {}
  878. };
  879. constexpr std::array<TransformTestcase, 8> testcases{
  880. TransformTestcase(Transform::NORMAL, crop_0),
  881. TransformTestcase(Transform::ROTATE_90, crop_90),
  882. TransformTestcase(Transform::ROTATE_180, crop_180),
  883. TransformTestcase(Transform::ROTATE_270, crop_270),
  884. TransformTestcase(Transform::FLIPPED, flipped_crop_0),
  885. TransformTestcase(Transform::FLIPPED_ROTATE_90, flipped_crop_90),
  886. TransformTestcase(Transform::FLIPPED_ROTATE_180, flipped_crop_180),
  887. TransformTestcase(Transform::FLIPPED_ROTATE_270, flipped_crop_270)};
  888. for (const auto& tc : testcases) {
  889. SetCropAndBufferTransformHelperTransformAndTest(
  890. surface.get(), shell_surface.get(), tc.transform,
  891. gfx::SkRectToRectF(tc.expected_rect), false);
  892. }
  893. surface->SetViewport(gfx::SizeF(128, 64));
  894. for (const auto& tc : testcases) {
  895. SetCropAndBufferTransformHelperTransformAndTest(
  896. surface.get(), shell_surface.get(), tc.transform,
  897. gfx::SkRectToRectF(tc.expected_rect), true);
  898. }
  899. }
  900. TEST_P(SurfaceTest, SetBlendMode) {
  901. gfx::Size buffer_size(1, 1);
  902. auto buffer = std::make_unique<Buffer>(
  903. exo_test_helper()->CreateGpuMemoryBuffer(buffer_size));
  904. auto surface = std::make_unique<Surface>();
  905. auto shell_surface = std::make_unique<ShellSurface>(surface.get());
  906. surface->Attach(buffer.get());
  907. surface->SetBlendMode(SkBlendMode::kSrc);
  908. surface->Commit();
  909. base::RunLoop().RunUntilIdle();
  910. const viz::CompositorFrame& frame = GetFrameFromSurface(shell_surface.get());
  911. ASSERT_EQ(1u, frame.render_pass_list.size());
  912. ASSERT_EQ(1u, frame.render_pass_list.back()->quad_list.size());
  913. EXPECT_FALSE(frame.render_pass_list.back()
  914. ->quad_list.back()
  915. ->ShouldDrawWithBlending());
  916. }
  917. TEST_P(SurfaceTest, OverlayCandidate) {
  918. gfx::Size buffer_size(1, 1);
  919. auto buffer = std::make_unique<Buffer>(
  920. exo_test_helper()->CreateGpuMemoryBuffer(buffer_size), GL_TEXTURE_2D, 0,
  921. true, true, false);
  922. auto surface = std::make_unique<Surface>();
  923. auto shell_surface = std::make_unique<ShellSurface>(surface.get());
  924. surface->Attach(buffer.get());
  925. surface->Commit();
  926. base::RunLoop().RunUntilIdle();
  927. const viz::CompositorFrame& frame = GetFrameFromSurface(shell_surface.get());
  928. ASSERT_EQ(1u, frame.render_pass_list.size());
  929. ASSERT_EQ(1u, frame.render_pass_list.back()->quad_list.size());
  930. viz::DrawQuad* draw_quad = frame.render_pass_list.back()->quad_list.back();
  931. ASSERT_EQ(viz::DrawQuad::Material::kTextureContent, draw_quad->material);
  932. const viz::TextureDrawQuad* texture_quad =
  933. viz::TextureDrawQuad::MaterialCast(draw_quad);
  934. EXPECT_FALSE(texture_quad->resource_size_in_pixels().IsEmpty());
  935. }
  936. TEST_P(SurfaceTest, SetAlpha) {
  937. gfx::Size buffer_size(1, 1);
  938. auto buffer = std::make_unique<Buffer>(
  939. exo_test_helper()->CreateGpuMemoryBuffer(buffer_size), GL_TEXTURE_2D, 0,
  940. true, true, false);
  941. auto surface = std::make_unique<Surface>();
  942. auto shell_surface = std::make_unique<ShellSurface>(surface.get());
  943. {
  944. surface->Attach(buffer.get());
  945. surface->SetAlpha(0.5f);
  946. surface->Commit();
  947. base::RunLoop().RunUntilIdle();
  948. const viz::CompositorFrame& frame =
  949. GetFrameFromSurface(shell_surface.get());
  950. ASSERT_EQ(1u, frame.render_pass_list.size());
  951. ASSERT_EQ(1u, frame.render_pass_list.back()->quad_list.size());
  952. ASSERT_EQ(1u, frame.resource_list.size());
  953. ASSERT_EQ(viz::ResourceId(1u), frame.resource_list.back().id);
  954. EXPECT_EQ(gfx::Rect(buffer_size), ToTargetSpaceDamage(frame));
  955. }
  956. {
  957. surface->SetAlpha(0.f);
  958. surface->Commit();
  959. base::RunLoop().RunUntilIdle();
  960. const viz::CompositorFrame& frame =
  961. GetFrameFromSurface(shell_surface.get());
  962. ASSERT_EQ(1u, frame.render_pass_list.size());
  963. // No quad if alpha is 0.
  964. ASSERT_EQ(0u, frame.render_pass_list.back()->quad_list.size());
  965. ASSERT_EQ(0u, frame.resource_list.size());
  966. EXPECT_EQ(gfx::Rect(buffer_size), ToTargetSpaceDamage(frame));
  967. }
  968. {
  969. surface->SetAlpha(1.f);
  970. surface->Commit();
  971. base::RunLoop().RunUntilIdle();
  972. const viz::CompositorFrame& frame =
  973. GetFrameFromSurface(shell_surface.get());
  974. ASSERT_EQ(1u, frame.render_pass_list.size());
  975. ASSERT_EQ(1u, frame.render_pass_list.back()->quad_list.size());
  976. ASSERT_EQ(1u, frame.resource_list.size());
  977. // The resource should be updated again, the id should be changed.
  978. ASSERT_EQ(viz::ResourceId(2u), frame.resource_list.back().id);
  979. EXPECT_EQ(gfx::Rect(buffer_size), ToTargetSpaceDamage(frame));
  980. }
  981. }
  982. TEST_P(SurfaceTest, SurfaceQuad) {
  983. gfx::Size buffer_size(1, 1);
  984. auto buffer = std::make_unique<Buffer>(
  985. exo_test_helper()->CreateGpuMemoryBuffer(buffer_size), GL_TEXTURE_2D, 0,
  986. true, true, false);
  987. auto surface = std::make_unique<Surface>();
  988. auto shell_surface = std::make_unique<ShellSurface>(surface.get());
  989. surface->Attach(buffer.get());
  990. surface->SetAlpha(1.0f);
  991. surface->SetEmbeddedSurfaceSize(gfx::Size(1, 1));
  992. surface->SetEmbeddedSurfaceId(base::BindRepeating([]() -> viz::SurfaceId {
  993. return viz::SurfaceId(
  994. viz::FrameSinkId(1, 1),
  995. viz::LocalSurfaceId(1, 1, base::UnguessableToken::Create()));
  996. }));
  997. {
  998. surface->Commit();
  999. base::RunLoop().RunUntilIdle();
  1000. const viz::CompositorFrame& frame =
  1001. GetFrameFromSurface(shell_surface.get());
  1002. EXPECT_EQ(1u, frame.render_pass_list.size());
  1003. EXPECT_EQ(1u, frame.render_pass_list.back()->quad_list.size());
  1004. EXPECT_EQ(1u, frame.resource_list.size());
  1005. // Ensure that the quad is correct and the resource is included.
  1006. EXPECT_EQ(viz::ResourceId(1u), frame.resource_list.back().id);
  1007. EXPECT_EQ(viz::DrawQuad::Material::kSurfaceContent,
  1008. frame.render_pass_list.back()->quad_list.back()->material);
  1009. }
  1010. }
  1011. TEST_P(SurfaceTest, EmptySurfaceQuad) {
  1012. gfx::Size buffer_size(1, 1);
  1013. auto buffer = std::make_unique<Buffer>(
  1014. exo_test_helper()->CreateGpuMemoryBuffer(buffer_size), GL_TEXTURE_2D, 0,
  1015. true, true, false);
  1016. auto surface = std::make_unique<Surface>();
  1017. auto shell_surface = std::make_unique<ShellSurface>(surface.get());
  1018. surface->Attach(buffer.get());
  1019. surface->SetAlpha(1.0f);
  1020. // Explicitly zero the size, no quad should be produced.
  1021. surface->SetEmbeddedSurfaceSize(gfx::Size(0, 0));
  1022. surface->SetEmbeddedSurfaceId(base::BindRepeating([]() -> viz::SurfaceId {
  1023. return viz::SurfaceId(
  1024. viz::FrameSinkId(1, 1),
  1025. viz::LocalSurfaceId(1, 1, base::UnguessableToken::Create()));
  1026. }));
  1027. {
  1028. surface->Commit();
  1029. base::RunLoop().RunUntilIdle();
  1030. const viz::CompositorFrame& frame =
  1031. GetFrameFromSurface(shell_surface.get());
  1032. EXPECT_EQ(1u, frame.render_pass_list.size());
  1033. EXPECT_EQ(0u, frame.render_pass_list.back()->quad_list.size());
  1034. // No quad but still has a resource though.
  1035. EXPECT_EQ(1u, frame.resource_list.size());
  1036. EXPECT_EQ(viz::ResourceId(1u), frame.resource_list.back().id);
  1037. }
  1038. }
  1039. TEST_P(SurfaceTest, ScaledSurfaceQuad) {
  1040. gfx::Size buffer_size(1, 1);
  1041. auto buffer = std::make_unique<Buffer>(
  1042. exo_test_helper()->CreateGpuMemoryBuffer(buffer_size), GL_TEXTURE_2D, 0,
  1043. true, true, false);
  1044. auto surface = std::make_unique<Surface>();
  1045. auto shell_surface = std::make_unique<ShellSurface>(surface.get());
  1046. surface->Attach(buffer.get());
  1047. surface->SetAlpha(1.0f);
  1048. surface->SetEmbeddedSurfaceId(base::BindRepeating([]() -> viz::SurfaceId {
  1049. return viz::SurfaceId(
  1050. viz::FrameSinkId(1, 1),
  1051. viz::LocalSurfaceId(1, 1, base::UnguessableToken::Create()));
  1052. }));
  1053. // A 256x256 surface, of which as 128x128 chunk is selected, drawn into a
  1054. // 128x64 rect.
  1055. surface->SetEmbeddedSurfaceSize(gfx::Size(256, 256));
  1056. surface->SetViewport(gfx::SizeF(128, 64));
  1057. surface->SetCrop(
  1058. gfx::RectF(gfx::PointF(32.0f, 32.0f), gfx::SizeF(128.0f, 128.0f)));
  1059. {
  1060. surface->Commit();
  1061. base::RunLoop().RunUntilIdle();
  1062. const viz::CompositorFrame& frame =
  1063. GetFrameFromSurface(shell_surface.get());
  1064. EXPECT_EQ(1u, frame.render_pass_list.size());
  1065. EXPECT_EQ(1u, frame.render_pass_list.back()->quad_list.size());
  1066. EXPECT_EQ(1u, frame.resource_list.size());
  1067. // Ensure that the quad is correct and the resource is included.
  1068. EXPECT_EQ(viz::ResourceId(1u), frame.resource_list.back().id);
  1069. EXPECT_EQ(viz::DrawQuad::Material::kSurfaceContent,
  1070. frame.render_pass_list.back()->quad_list.back()->material);
  1071. // We are outputting to 0,0 -> 128,64.
  1072. EXPECT_EQ(gfx::Rect(gfx::Point(), gfx::Size(128, 64)),
  1073. frame.render_pass_list.back()
  1074. ->quad_list.back()
  1075. ->shared_quad_state->clip_rect);
  1076. auto testing_rect = gfx::RectF(gfx::PointF(0, 0), gfx::SizeF(256, 256));
  1077. // To get 32,32 -> 160,160 into the correct position it must be translated
  1078. // backwards and scaled 0.5x in Y, then everything is scaled by the scale
  1079. // factor.
  1080. auto expected_transform = gfx::Transform(
  1081. 1.0f * device_scale_factor(), 0.0f, 0.0f, 0.5f * device_scale_factor(),
  1082. -32.0f * device_scale_factor(), -32.0f * device_scale_factor() * 0.5f);
  1083. // When possible exo will represent the transform completely in the |rect|.
  1084. // This leaves the |quad_to_target_transform| transform as Identity.
  1085. if (gfx::Transform() == frame.render_pass_list.back()
  1086. ->quad_list.back()
  1087. ->shared_quad_state->quad_to_target_transform) {
  1088. expected_transform.TransformRect(&testing_rect);
  1089. auto expected_rect = gfx::ToNearestRect(testing_rect);
  1090. EXPECT_EQ(expected_rect,
  1091. frame.render_pass_list.back()->quad_list.back()->rect);
  1092. } else {
  1093. EXPECT_EQ(expected_transform,
  1094. frame.render_pass_list.back()
  1095. ->quad_list.back()
  1096. ->shared_quad_state->quad_to_target_transform);
  1097. EXPECT_EQ(gfx::ToNearestRect(testing_rect),
  1098. frame.render_pass_list.back()->quad_list.back()->rect);
  1099. }
  1100. }
  1101. }
  1102. TEST_P(SurfaceTest, ColorBufferAlpha) {
  1103. gfx::Size buffer_size(1, 1);
  1104. constexpr SkColor4f kBuffColorExpected[] = {{1.f, 128.0f / 255.0f, 0.f, 1.f},
  1105. {0.f, 128.0f / 255.0f, 1.f, 0.f}};
  1106. constexpr bool kExpectedOpaque[] = {true, false};
  1107. for (size_t i = 0; i < std::size(kBuffColorExpected); i++) {
  1108. auto buffer =
  1109. std::make_unique<SolidColorBuffer>(kBuffColorExpected[i], buffer_size);
  1110. auto surface = std::make_unique<Surface>();
  1111. auto shell_surface = std::make_unique<ShellSurface>(surface.get());
  1112. surface->Attach(buffer.get());
  1113. surface->SetAlpha(1.0f);
  1114. surface->SetEmbeddedSurfaceSize(gfx::Size(1, 1));
  1115. surface->SetEmbeddedSurfaceId(base::BindRepeating([]() -> viz::SurfaceId {
  1116. return viz::SurfaceId(
  1117. viz::FrameSinkId(1, 1),
  1118. viz::LocalSurfaceId(1, 1, base::UnguessableToken::Create()));
  1119. }));
  1120. {
  1121. surface->Commit();
  1122. base::RunLoop().RunUntilIdle();
  1123. const viz::CompositorFrame& frame =
  1124. GetFrameFromSurface(shell_surface.get());
  1125. EXPECT_EQ(1u, frame.render_pass_list.size());
  1126. EXPECT_EQ(1u, frame.render_pass_list.back()->quad_list.size());
  1127. EXPECT_EQ(0u, frame.resource_list.size());
  1128. auto* draw_quad = frame.render_pass_list.back()->quad_list.back();
  1129. EXPECT_EQ(viz::DrawQuad::Material::kSolidColor, draw_quad->material);
  1130. EXPECT_EQ(kExpectedOpaque[i],
  1131. draw_quad->shared_quad_state->are_contents_opaque);
  1132. auto* solid_color_quad = viz::SolidColorDrawQuad::MaterialCast(draw_quad);
  1133. EXPECT_EQ(kBuffColorExpected[i], solid_color_quad->color);
  1134. }
  1135. }
  1136. }
  1137. TEST_P(SurfaceTest, Commit) {
  1138. std::unique_ptr<Surface> surface(new Surface);
  1139. // Calling commit without a buffer should succeed.
  1140. surface->Commit();
  1141. }
  1142. TEST_P(SurfaceTest, RemoveSubSurface) {
  1143. gfx::Size buffer_size(256, 256);
  1144. std::unique_ptr<Buffer> buffer(
  1145. new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size)));
  1146. std::unique_ptr<Surface> surface(new Surface);
  1147. auto shell_surface = std::make_unique<ShellSurface>(surface.get());
  1148. surface->Attach(buffer.get());
  1149. // Create a subsurface:
  1150. gfx::Size child_buffer_size(64, 128);
  1151. auto child_buffer = std::make_unique<Buffer>(
  1152. exo_test_helper()->CreateGpuMemoryBuffer(child_buffer_size));
  1153. auto child_surface = std::make_unique<Surface>();
  1154. auto sub_surface =
  1155. std::make_unique<SubSurface>(child_surface.get(), surface.get());
  1156. sub_surface->SetPosition(gfx::PointF(20, 10));
  1157. child_surface->Attach(child_buffer.get());
  1158. child_surface->Commit();
  1159. surface->Commit();
  1160. base::RunLoop().RunUntilIdle();
  1161. // Remove the subsurface by destroying it. This should not damage |surface|.
  1162. // TODO(penghuang): Make the damage more precise for sub surface changes.
  1163. // https://crbug.com/779704
  1164. sub_surface.reset();
  1165. EXPECT_FALSE(surface->HasPendingDamageForTesting(gfx::Rect(20, 10, 64, 128)));
  1166. }
  1167. TEST_P(SurfaceTest, DestroyAttachedBuffer) {
  1168. gfx::Size buffer_size(1, 1);
  1169. auto buffer = std::make_unique<Buffer>(
  1170. exo_test_helper()->CreateGpuMemoryBuffer(buffer_size));
  1171. auto surface = std::make_unique<Surface>();
  1172. auto shell_surface = std::make_unique<ShellSurface>(surface.get());
  1173. surface->Attach(buffer.get());
  1174. surface->Commit();
  1175. base::RunLoop().RunUntilIdle();
  1176. // Make sure surface size is still valid after buffer is destroyed.
  1177. buffer.reset();
  1178. surface->Commit();
  1179. EXPECT_FALSE(surface->content_size().IsEmpty());
  1180. }
  1181. TEST_P(SurfaceTest, SetClientSurfaceId) {
  1182. auto surface = std::make_unique<Surface>();
  1183. const std::string kTestId = "42";
  1184. surface->SetClientSurfaceId(kTestId.c_str());
  1185. EXPECT_EQ(kTestId, surface->GetClientSurfaceId());
  1186. }
  1187. TEST_P(SurfaceTest, DestroyWithAttachedBufferReleasesBuffer) {
  1188. gfx::Size buffer_size(1, 1);
  1189. auto buffer = std::make_unique<Buffer>(
  1190. exo_test_helper()->CreateGpuMemoryBuffer(buffer_size));
  1191. auto surface = std::make_unique<Surface>();
  1192. auto shell_surface = std::make_unique<ShellSurface>(surface.get());
  1193. int release_buffer_call_count = 0;
  1194. buffer->set_release_callback(base::BindRepeating(
  1195. &ReleaseBuffer, base::Unretained(&release_buffer_call_count)));
  1196. surface->Attach(buffer.get());
  1197. surface->Commit();
  1198. base::RunLoop().RunUntilIdle();
  1199. // Buffer is still attached at this point.
  1200. EXPECT_EQ(0, release_buffer_call_count);
  1201. // After the surface is destroyed, we should get a release event for the
  1202. // attached buffer.
  1203. shell_surface.reset();
  1204. surface.reset();
  1205. base::RunLoop().RunUntilIdle();
  1206. ASSERT_EQ(1, release_buffer_call_count);
  1207. }
  1208. TEST_P(SurfaceTest, AcquireFence) {
  1209. auto buffer = std::make_unique<Buffer>(
  1210. exo_test_helper()->CreateGpuMemoryBuffer(gfx::Size(1, 1)));
  1211. auto surface = std::make_unique<Surface>();
  1212. // We can only commit an acquire fence if a buffer is attached.
  1213. surface->Attach(buffer.get());
  1214. EXPECT_FALSE(surface->HasPendingAcquireFence());
  1215. surface->SetAcquireFence(
  1216. std::make_unique<gfx::GpuFence>(gfx::GpuFenceHandle()));
  1217. EXPECT_TRUE(surface->HasPendingAcquireFence());
  1218. surface->Commit();
  1219. EXPECT_FALSE(surface->HasPendingAcquireFence());
  1220. }
  1221. TEST_P(SurfaceTest, UpdatesOcclusionOnDestroyingSubsurface) {
  1222. gfx::Size buffer_size(256, 512);
  1223. auto buffer = std::make_unique<Buffer>(
  1224. exo_test_helper()->CreateGpuMemoryBuffer(buffer_size));
  1225. auto surface = std::make_unique<Surface>();
  1226. auto shell_surface = std::make_unique<ShellSurface>(surface.get());
  1227. surface->Attach(buffer.get());
  1228. surface->Commit();
  1229. gfx::Size child_buffer_size(64, 128);
  1230. auto child_buffer = std::make_unique<Buffer>(
  1231. exo_test_helper()->CreateGpuMemoryBuffer(child_buffer_size));
  1232. auto child_surface = std::make_unique<Surface>();
  1233. auto sub_surface =
  1234. std::make_unique<SubSurface>(child_surface.get(), surface.get());
  1235. child_surface->Attach(child_buffer.get());
  1236. // Turn on occlusion tracking.
  1237. child_surface->SetOcclusionTracking(true);
  1238. child_surface->Commit();
  1239. surface->Commit();
  1240. SurfaceObserverForTest observer;
  1241. ScopedSurface scoped_child_surface(child_surface.get(), &observer);
  1242. // Destroy the subsurface and expect to get an occlusion update.
  1243. sub_surface.reset();
  1244. EXPECT_EQ(1, observer.num_occlusion_changes());
  1245. EXPECT_EQ(aura::Window::OcclusionState::HIDDEN,
  1246. child_surface->window()->GetOcclusionState());
  1247. }
  1248. TEST_P(SurfaceTest, HasPendingPerCommitBufferReleaseCallback) {
  1249. auto buffer = std::make_unique<Buffer>(
  1250. exo_test_helper()->CreateGpuMemoryBuffer(gfx::Size(1, 1)));
  1251. auto surface = std::make_unique<Surface>();
  1252. // We can only commit a buffer release callback if a buffer is attached.
  1253. surface->Attach(buffer.get());
  1254. EXPECT_FALSE(surface->HasPendingPerCommitBufferReleaseCallback());
  1255. surface->SetPerCommitBufferReleaseCallback(
  1256. base::BindOnce([](gfx::GpuFenceHandle) {}));
  1257. EXPECT_TRUE(surface->HasPendingPerCommitBufferReleaseCallback());
  1258. surface->Commit();
  1259. base::RunLoop().RunUntilIdle();
  1260. EXPECT_FALSE(surface->HasPendingPerCommitBufferReleaseCallback());
  1261. }
  1262. // TODO(crbug.com/1292674): Flaky on ChromeOS.
  1263. #if BUILDFLAG(IS_CHROMEOS)
  1264. #define MAYBE_PerCommitBufferReleaseCallbackForSameSurface \
  1265. DISABLED_PerCommitBufferReleaseCallbackForSameSurface
  1266. #else
  1267. #define MAYBE_PerCommitBufferReleaseCallbackForSameSurface \
  1268. PerCommitBufferReleaseCallbackForSameSurface
  1269. #endif
  1270. TEST_P(SurfaceTest, MAYBE_PerCommitBufferReleaseCallbackForSameSurface) {
  1271. gfx::Size buffer_size(1, 1);
  1272. auto buffer1 = std::make_unique<Buffer>(
  1273. exo_test_helper()->CreateGpuMemoryBuffer(buffer_size));
  1274. auto buffer2 = std::make_unique<Buffer>(
  1275. exo_test_helper()->CreateGpuMemoryBuffer(buffer_size));
  1276. auto surface = std::make_unique<Surface>();
  1277. auto shell_surface = std::make_unique<ShellSurface>(surface.get());
  1278. int per_commit_release_count = 0;
  1279. // Set the release callback that will be run when buffer is no longer in use.
  1280. int buffer_release_count = 0;
  1281. buffer1->set_release_callback(base::BindRepeating(
  1282. &ReleaseBuffer, base::Unretained(&buffer_release_count)));
  1283. surface->SetPerCommitBufferReleaseCallback(base::BindOnce(
  1284. &ExplicitReleaseBuffer, base::Unretained(&per_commit_release_count)));
  1285. surface->Attach(buffer1.get());
  1286. surface->Commit();
  1287. base::RunLoop().RunUntilIdle();
  1288. EXPECT_EQ(per_commit_release_count, 0);
  1289. EXPECT_EQ(buffer_release_count, 0);
  1290. // Attaching the same buffer causes the per-commit callback to be emitted.
  1291. surface->SetPerCommitBufferReleaseCallback(base::BindOnce(
  1292. &ExplicitReleaseBuffer, base::Unretained(&per_commit_release_count)));
  1293. surface->Attach(buffer1.get());
  1294. surface->Commit();
  1295. base::RunLoop().RunUntilIdle();
  1296. EXPECT_EQ(per_commit_release_count, 1);
  1297. EXPECT_EQ(buffer_release_count, 0);
  1298. // Attaching a different buffer causes the per-commit callback to be emitted.
  1299. surface->Attach(buffer2.get());
  1300. surface->Commit();
  1301. base::RunLoop().RunUntilIdle();
  1302. EXPECT_EQ(per_commit_release_count, 2);
  1303. // The buffer should now be completely released.
  1304. EXPECT_EQ(buffer_release_count, 1);
  1305. }
  1306. // TODO(crbug.com/1292674): Flaky on ChromeOS.
  1307. #if BUILDFLAG(IS_CHROMEOS)
  1308. #define MAYBE_PerCommitBufferReleaseCallbackForDifferentSurfaces \
  1309. DISABLED_PerCommitBufferReleaseCallbackForDifferentSurfaces
  1310. #else
  1311. #define MAYBE_PerCommitBufferReleaseCallbackForDifferentSurfaces \
  1312. PerCommitBufferReleaseCallbackForDifferentSurfaces
  1313. #endif
  1314. TEST_P(SurfaceTest, MAYBE_PerCommitBufferReleaseCallbackForDifferentSurfaces) {
  1315. gfx::Size buffer_size(1, 1);
  1316. auto buffer1 = std::make_unique<Buffer>(
  1317. exo_test_helper()->CreateGpuMemoryBuffer(buffer_size));
  1318. auto buffer2 = std::make_unique<Buffer>(
  1319. exo_test_helper()->CreateGpuMemoryBuffer(buffer_size));
  1320. auto surface1 = std::make_unique<Surface>();
  1321. auto shell_surface1 = std::make_unique<ShellSurface>(surface1.get());
  1322. auto surface2 = std::make_unique<Surface>();
  1323. auto shell_surface2 = std::make_unique<ShellSurface>(surface2.get());
  1324. int per_commit_release_count1 = 0;
  1325. int per_commit_release_count2 = 0;
  1326. // Set the release callback that will be run when buffer is no longer in use.
  1327. int buffer_release_count = 0;
  1328. buffer1->set_release_callback(base::BindRepeating(
  1329. &ReleaseBuffer, base::Unretained(&buffer_release_count)));
  1330. // Attach buffer1 to both surface1 and surface2.
  1331. surface1->SetPerCommitBufferReleaseCallback(base::BindOnce(
  1332. &ExplicitReleaseBuffer, base::Unretained(&per_commit_release_count1)));
  1333. surface1->Attach(buffer1.get());
  1334. surface1->Commit();
  1335. surface2->SetPerCommitBufferReleaseCallback(base::BindOnce(
  1336. &ExplicitReleaseBuffer, base::Unretained(&per_commit_release_count2)));
  1337. surface2->Attach(buffer1.get());
  1338. surface2->Commit();
  1339. base::RunLoop().RunUntilIdle();
  1340. EXPECT_EQ(per_commit_release_count1, 0);
  1341. EXPECT_EQ(per_commit_release_count2, 0);
  1342. EXPECT_EQ(buffer_release_count, 0);
  1343. // Attach buffer2 to surface1, only the surface1 callback should be emitted.
  1344. surface1->Attach(buffer2.get());
  1345. surface1->Commit();
  1346. base::RunLoop().RunUntilIdle();
  1347. EXPECT_EQ(per_commit_release_count1, 1);
  1348. EXPECT_EQ(per_commit_release_count2, 0);
  1349. EXPECT_EQ(buffer_release_count, 0);
  1350. // Attach buffer2 to surface2, only the surface2 callback should be emitted.
  1351. surface2->Attach(buffer2.get());
  1352. surface2->Commit();
  1353. base::RunLoop().RunUntilIdle();
  1354. EXPECT_EQ(per_commit_release_count1, 1);
  1355. EXPECT_EQ(per_commit_release_count2, 1);
  1356. // The buffer should now be completely released.
  1357. EXPECT_EQ(buffer_release_count, 1);
  1358. }
  1359. } // namespace
  1360. } // namespace exo