client_resource_provider_unittest.cc 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842
  1. // Copyright 2017 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/viz/client/client_resource_provider.h"
  5. #include <algorithm>
  6. #include <memory>
  7. #include <utility>
  8. #include "base/bind.h"
  9. #include "base/callback_helpers.h"
  10. #include "base/test/gtest_util.h"
  11. #include "components/viz/common/resources/release_callback.h"
  12. #include "components/viz/common/resources/returned_resource.h"
  13. #include "components/viz/test/test_context_provider.h"
  14. #include "gpu/command_buffer/common/shared_image_usage.h"
  15. #include "testing/gmock/include/gmock/gmock.h"
  16. #include "testing/gtest/include/gtest/gtest.h"
  17. using testing::_;
  18. using testing::Each;
  19. namespace viz {
  20. namespace {
  21. class ClientResourceProviderTest : public testing::TestWithParam<bool> {
  22. protected:
  23. ClientResourceProviderTest()
  24. : use_gpu_(GetParam()),
  25. context_provider_(TestContextProvider::Create()),
  26. bound_(context_provider_->BindToCurrentThread()) {
  27. DCHECK_EQ(bound_, gpu::ContextResult::kSuccess);
  28. }
  29. void SetUp() override {
  30. provider_ = std::make_unique<ClientResourceProvider>();
  31. }
  32. void TearDown() override { provider_ = nullptr; }
  33. gpu::Mailbox MailboxFromChar(char value) {
  34. gpu::Mailbox mailbox;
  35. memset(mailbox.name, value, sizeof(mailbox.name));
  36. return mailbox;
  37. }
  38. gpu::SyncToken SyncTokenFromUInt(uint32_t value) {
  39. return gpu::SyncToken(gpu::CommandBufferNamespace::GPU_IO,
  40. gpu::CommandBufferId::FromUnsafeValue(0x123), value);
  41. }
  42. TransferableResource MakeTransferableResource(bool gpu,
  43. char mailbox_char,
  44. uint32_t sync_token_value) {
  45. TransferableResource r;
  46. r.id = ResourceId(mailbox_char);
  47. r.is_software = !gpu;
  48. r.filter = 456;
  49. r.size = gfx::Size(10, 11);
  50. r.mailbox_holder.mailbox = MailboxFromChar(mailbox_char);
  51. if (gpu) {
  52. r.mailbox_holder.sync_token = SyncTokenFromUInt(sync_token_value);
  53. r.mailbox_holder.texture_target = 6;
  54. }
  55. return r;
  56. }
  57. bool use_gpu() const { return use_gpu_; }
  58. ClientResourceProvider& provider() const { return *provider_; }
  59. ContextProvider* context_provider() const { return context_provider_.get(); }
  60. void DestroyProvider() {
  61. provider_->ShutdownAndReleaseAllResources();
  62. provider_ = nullptr;
  63. }
  64. private:
  65. bool use_gpu_;
  66. scoped_refptr<TestContextProvider> context_provider_;
  67. gpu::ContextResult bound_;
  68. std::unique_ptr<ClientResourceProvider> provider_;
  69. };
  70. INSTANTIATE_TEST_SUITE_P(ClientResourceProviderTests,
  71. ClientResourceProviderTest,
  72. ::testing::Values(false, true));
  73. class MockReleaseCallback {
  74. public:
  75. MOCK_METHOD2(Released, void(const gpu::SyncToken& token, bool lost));
  76. MOCK_METHOD3(ReleasedWithId,
  77. void(ResourceId id, const gpu::SyncToken& token, bool lost));
  78. };
  79. TEST_P(ClientResourceProviderTest, TransferableResourceReleased) {
  80. MockReleaseCallback release;
  81. TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 15);
  82. ResourceId id = provider().ImportResource(
  83. tran, base::BindOnce(&MockReleaseCallback::Released,
  84. base::Unretained(&release)));
  85. // The local id is different.
  86. EXPECT_NE(id, tran.id);
  87. // The same SyncToken that was sent is returned when the resource was never
  88. // exported. The SyncToken may be from any context, and the ReleaseCallback
  89. // may need to wait on it before interacting with the resource on its context.
  90. EXPECT_CALL(release, Released(tran.mailbox_holder.sync_token, false));
  91. provider().RemoveImportedResource(id);
  92. }
  93. TEST_P(ClientResourceProviderTest, TransferableResourceSendToParent) {
  94. MockReleaseCallback release;
  95. TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 15);
  96. ResourceId id = provider().ImportResource(
  97. tran, base::BindOnce(&MockReleaseCallback::Released,
  98. base::Unretained(&release)));
  99. // Export the resource.
  100. std::vector<ResourceId> to_send = {id};
  101. std::vector<TransferableResource> exported;
  102. provider().PrepareSendToParent(to_send, &exported, context_provider());
  103. ASSERT_EQ(exported.size(), 1u);
  104. // Exported resource matches except for the id which was mapped
  105. // to the local ResourceProvider, and the sync token should be
  106. // verified if it's a gpu resource.
  107. gpu::SyncToken verified_sync_token = tran.mailbox_holder.sync_token;
  108. if (!tran.is_software)
  109. verified_sync_token.SetVerifyFlush();
  110. EXPECT_EQ(exported[0].id, id);
  111. EXPECT_EQ(exported[0].is_software, tran.is_software);
  112. EXPECT_EQ(exported[0].filter, tran.filter);
  113. EXPECT_EQ(exported[0].size, tran.size);
  114. EXPECT_EQ(exported[0].mailbox_holder.mailbox, tran.mailbox_holder.mailbox);
  115. EXPECT_EQ(exported[0].mailbox_holder.sync_token, verified_sync_token);
  116. EXPECT_EQ(exported[0].mailbox_holder.texture_target,
  117. tran.mailbox_holder.texture_target);
  118. // Exported resources are not released when removed, until the export returns.
  119. EXPECT_CALL(release, Released(_, _)).Times(0);
  120. provider().RemoveImportedResource(id);
  121. // Return the resource, with a sync token if using gpu.
  122. std::vector<ReturnedResource> returned;
  123. returned.emplace_back();
  124. returned.back().id = exported[0].id;
  125. if (use_gpu())
  126. returned.back().sync_token = SyncTokenFromUInt(31);
  127. returned.back().count = 1;
  128. returned.back().lost = false;
  129. // The sync token is given to the ReleaseCallback.
  130. EXPECT_CALL(release, Released(returned[0].sync_token, false));
  131. provider().ReceiveReturnsFromParent(std::move(returned));
  132. }
  133. TEST_P(ClientResourceProviderTest, TransferableResourceSendTwoToParent) {
  134. TransferableResource tran[] = {MakeTransferableResource(use_gpu(), 'a', 15),
  135. MakeTransferableResource(use_gpu(), 'b', 16)};
  136. ResourceId id1 = provider().ImportResource(tran[0], base::DoNothing());
  137. ResourceId id2 = provider().ImportResource(tran[1], base::DoNothing());
  138. // Export the resource.
  139. std::vector<ResourceId> to_send = {id1, id2};
  140. std::vector<TransferableResource> exported;
  141. provider().PrepareSendToParent(to_send, &exported, context_provider());
  142. ASSERT_EQ(exported.size(), 2u);
  143. // Exported resource matches except for the id which was mapped
  144. // to the local ResourceProvider, and the sync token should be
  145. // verified if it's a gpu resource.
  146. for (int i = 0; i < 2; ++i) {
  147. gpu::SyncToken verified_sync_token = tran[i].mailbox_holder.sync_token;
  148. if (!tran[i].is_software)
  149. verified_sync_token.SetVerifyFlush();
  150. EXPECT_EQ(exported[i].id, to_send[i]);
  151. EXPECT_EQ(exported[i].is_software, tran[i].is_software);
  152. EXPECT_EQ(exported[i].filter, tran[i].filter);
  153. EXPECT_EQ(exported[i].size, tran[i].size);
  154. EXPECT_EQ(exported[i].mailbox_holder.mailbox,
  155. tran[i].mailbox_holder.mailbox);
  156. EXPECT_EQ(exported[i].mailbox_holder.sync_token, verified_sync_token);
  157. EXPECT_EQ(exported[i].mailbox_holder.texture_target,
  158. tran[i].mailbox_holder.texture_target);
  159. }
  160. provider().RemoveImportedResource(id1);
  161. provider().RemoveImportedResource(id2);
  162. DestroyProvider();
  163. }
  164. TEST_P(ClientResourceProviderTest, TransferableResourceSendToParentTwoTimes) {
  165. TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 15);
  166. ResourceId id = provider().ImportResource(tran, base::DoNothing());
  167. // Export the resource.
  168. std::vector<ResourceId> to_send = {id};
  169. std::vector<TransferableResource> exported;
  170. provider().PrepareSendToParent(to_send, &exported, context_provider());
  171. ASSERT_EQ(exported.size(), 1u);
  172. EXPECT_EQ(exported[0].id, id);
  173. // Return the resource, with a sync token if using gpu.
  174. std::vector<ReturnedResource> returned;
  175. returned.emplace_back();
  176. returned.back().id = exported[0].id;
  177. if (use_gpu())
  178. returned.back().sync_token = SyncTokenFromUInt(31);
  179. returned.back().count = 1;
  180. returned.back().lost = false;
  181. provider().ReceiveReturnsFromParent(std::move(returned));
  182. // Then export again, it still sends.
  183. exported.clear();
  184. provider().PrepareSendToParent(to_send, &exported, context_provider());
  185. ASSERT_EQ(exported.size(), 1u);
  186. EXPECT_EQ(exported[0].id, id);
  187. provider().RemoveImportedResource(id);
  188. DestroyProvider();
  189. }
  190. TEST_P(ClientResourceProviderTest,
  191. TransferableResourceLostOnShutdownIfExported) {
  192. MockReleaseCallback release;
  193. TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 15);
  194. ResourceId id = provider().ImportResource(
  195. tran, base::BindOnce(&MockReleaseCallback::Released,
  196. base::Unretained(&release)));
  197. // Export the resource.
  198. std::vector<ResourceId> to_send = {id};
  199. std::vector<TransferableResource> exported;
  200. provider().PrepareSendToParent(to_send, &exported, context_provider());
  201. provider().RemoveImportedResource(id);
  202. EXPECT_CALL(release, Released(_, true));
  203. DestroyProvider();
  204. }
  205. TEST_P(ClientResourceProviderTest, TransferableResourceSendToParentManyUnsent) {
  206. MockReleaseCallback release;
  207. // 5 resources to have 2 before and 2 after the one being sent and returned,
  208. // to verify the data structures are treated correctly when removing from the
  209. // middle. 1 after is not enough as that one will replace the resource being
  210. // removed and misses some edge cases. We want another resource after that in
  211. // the structure to verify it is also not treated incorrectly.
  212. struct Data {
  213. TransferableResource tran;
  214. ResourceId id;
  215. } data[5];
  216. for (int i = 0; i < 5; ++i) {
  217. data[i].tran = MakeTransferableResource(use_gpu(), 'a', 15);
  218. data[i].id = provider().ImportResource(
  219. data[i].tran, base::BindOnce(&MockReleaseCallback::Released,
  220. base::Unretained(&release)));
  221. }
  222. std::sort(std::begin(data), std::end(data),
  223. [](const Data& a, const Data& b) { return a.id < b.id; });
  224. // Export the resource.
  225. std::vector<ResourceId> to_send = {data[2].id};
  226. std::vector<TransferableResource> exported;
  227. provider().PrepareSendToParent(to_send, &exported, context_provider());
  228. ASSERT_EQ(exported.size(), 1u);
  229. // Exported resource matches except for the id which was mapped
  230. // to the local ResourceProvider, and the sync token should be
  231. // verified if it's a gpu resource.
  232. gpu::SyncToken verified_sync_token = data[2].tran.mailbox_holder.sync_token;
  233. if (!data[2].tran.is_software)
  234. verified_sync_token.SetVerifyFlush();
  235. // Exported resources are not released when removed, until the export returns.
  236. EXPECT_CALL(release, Released(_, _)).Times(0);
  237. provider().RemoveImportedResource(data[2].id);
  238. // Return the resource, with a sync token if using gpu.
  239. std::vector<ReturnedResource> returned;
  240. returned.emplace_back();
  241. returned.back().id = exported[0].id;
  242. if (use_gpu())
  243. returned.back().sync_token = SyncTokenFromUInt(31);
  244. returned.back().count = 1;
  245. returned.back().lost = false;
  246. // The sync token is given to the ReleaseCallback.
  247. EXPECT_CALL(release, Released(returned[0].sync_token, false));
  248. provider().ReceiveReturnsFromParent(std::move(returned));
  249. EXPECT_CALL(release, Released(_, false)).Times(4);
  250. provider().RemoveImportedResource(data[0].id);
  251. provider().RemoveImportedResource(data[1].id);
  252. provider().RemoveImportedResource(data[3].id);
  253. provider().RemoveImportedResource(data[4].id);
  254. }
  255. TEST_P(ClientResourceProviderTest, TransferableResourceRemovedAfterReturn) {
  256. MockReleaseCallback release;
  257. TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 15);
  258. ResourceId id = provider().ImportResource(
  259. tran, base::BindOnce(&MockReleaseCallback::Released,
  260. base::Unretained(&release)));
  261. // Export the resource.
  262. std::vector<ResourceId> to_send = {id};
  263. std::vector<TransferableResource> exported;
  264. provider().PrepareSendToParent(to_send, &exported, context_provider());
  265. // Return the resource. This does not release the resource back to
  266. // the client.
  267. std::vector<ReturnedResource> returned;
  268. returned.emplace_back();
  269. returned.back().id = exported[0].id;
  270. if (use_gpu())
  271. returned.back().sync_token = SyncTokenFromUInt(31);
  272. returned.back().count = 1;
  273. returned.back().lost = false;
  274. EXPECT_CALL(release, Released(_, _)).Times(0);
  275. auto sync_token = returned.back().sync_token;
  276. provider().ReceiveReturnsFromParent(std::move(returned));
  277. testing::Mock::VerifyAndClearExpectations(&release);
  278. // Once removed, the resource is released.
  279. EXPECT_CALL(release, Released(sync_token, false));
  280. provider().RemoveImportedResource(id);
  281. }
  282. TEST_P(ClientResourceProviderTest, TransferableResourceExportedTwice) {
  283. MockReleaseCallback release;
  284. TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 15);
  285. ResourceId id = provider().ImportResource(
  286. tran, base::BindOnce(&MockReleaseCallback::Released,
  287. base::Unretained(&release)));
  288. // Export the resource once.
  289. std::vector<ResourceId> to_send = {id};
  290. std::vector<TransferableResource> exported;
  291. provider().PrepareSendToParent(to_send, &exported, context_provider());
  292. // Exported resources are not released when removed, until all exports are
  293. // returned.
  294. EXPECT_CALL(release, Released(_, _)).Times(0);
  295. provider().RemoveImportedResource(id);
  296. // Export the resource twice.
  297. exported = {};
  298. provider().PrepareSendToParent(to_send, &exported, context_provider());
  299. {
  300. // Return the resource the first time.
  301. std::vector<ReturnedResource> returned;
  302. returned.emplace_back();
  303. returned.back().id = exported[0].id;
  304. if (use_gpu())
  305. returned.back().sync_token = SyncTokenFromUInt(31);
  306. returned.back().count = 1;
  307. returned.back().lost = false;
  308. provider().ReceiveReturnsFromParent(std::move(returned));
  309. }
  310. {
  311. // And a second time, with a different sync token. Now the ReleaseCallback
  312. // can happen, using the latest sync token.
  313. std::vector<ReturnedResource> returned;
  314. returned.emplace_back();
  315. returned.back().id = exported[0].id;
  316. if (use_gpu())
  317. returned.back().sync_token = SyncTokenFromUInt(47);
  318. returned.back().count = 1;
  319. returned.back().lost = false;
  320. EXPECT_CALL(release, Released(returned[0].sync_token, false));
  321. provider().ReceiveReturnsFromParent(std::move(returned));
  322. }
  323. }
  324. TEST_P(ClientResourceProviderTest, TransferableResourceReturnedTwiceAtOnce) {
  325. MockReleaseCallback release;
  326. TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 15);
  327. ResourceId id = provider().ImportResource(
  328. tran, base::BindOnce(&MockReleaseCallback::Released,
  329. base::Unretained(&release)));
  330. // Export the resource once.
  331. std::vector<ResourceId> to_send = {id};
  332. std::vector<TransferableResource> exported;
  333. provider().PrepareSendToParent(to_send, &exported, context_provider());
  334. // Exported resources are not released when removed, until all exports are
  335. // returned.
  336. EXPECT_CALL(release, Released(_, _)).Times(0);
  337. provider().RemoveImportedResource(id);
  338. // Export the resource twice.
  339. exported = {};
  340. provider().PrepareSendToParent(to_send, &exported, context_provider());
  341. // Return both exports at once.
  342. std::vector<ReturnedResource> returned;
  343. returned.emplace_back();
  344. returned.back().id = exported[0].id;
  345. if (use_gpu())
  346. returned.back().sync_token = SyncTokenFromUInt(31);
  347. returned.back().count = 2;
  348. returned.back().lost = false;
  349. // When returned, the ReleaseCallback can happen, using the latest sync token.
  350. EXPECT_CALL(release, Released(returned[0].sync_token, false));
  351. provider().ReceiveReturnsFromParent(std::move(returned));
  352. }
  353. TEST_P(ClientResourceProviderTest, TransferableResourceLostOnReturn) {
  354. MockReleaseCallback release;
  355. TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 15);
  356. ResourceId id = provider().ImportResource(
  357. tran, base::BindOnce(&MockReleaseCallback::Released,
  358. base::Unretained(&release)));
  359. // Export the resource once.
  360. std::vector<ResourceId> to_send = {id};
  361. std::vector<TransferableResource> exported;
  362. provider().PrepareSendToParent(to_send, &exported, context_provider());
  363. // Exported resources are not released when removed, until all exports are
  364. // returned.
  365. EXPECT_CALL(release, Released(_, _)).Times(0);
  366. provider().RemoveImportedResource(id);
  367. // Export the resource twice.
  368. exported = {};
  369. provider().PrepareSendToParent(to_send, &exported, context_provider());
  370. {
  371. // Return the resource the first time, not lost.
  372. std::vector<ReturnedResource> returned;
  373. returned.emplace_back();
  374. returned.back().id = exported[0].id;
  375. returned.back().count = 1;
  376. returned.back().lost = false;
  377. provider().ReceiveReturnsFromParent(std::move(returned));
  378. }
  379. {
  380. // Return a second time, as lost. The ReturnCallback should report it
  381. // lost.
  382. std::vector<ReturnedResource> returned;
  383. returned.emplace_back();
  384. returned.back().id = exported[0].id;
  385. returned.back().count = 1;
  386. returned.back().lost = true;
  387. EXPECT_CALL(release, Released(_, true));
  388. provider().ReceiveReturnsFromParent(std::move(returned));
  389. }
  390. }
  391. TEST_P(ClientResourceProviderTest, TransferableResourceLostOnFirstReturn) {
  392. MockReleaseCallback release;
  393. TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 15);
  394. ResourceId id = provider().ImportResource(
  395. tran, base::BindOnce(&MockReleaseCallback::Released,
  396. base::Unretained(&release)));
  397. // Export the resource once.
  398. std::vector<ResourceId> to_send = {id};
  399. std::vector<TransferableResource> exported;
  400. provider().PrepareSendToParent(to_send, &exported, context_provider());
  401. // Exported resources are not released when removed, until all exports are
  402. // returned.
  403. EXPECT_CALL(release, Released(_, _)).Times(0);
  404. provider().RemoveImportedResource(id);
  405. // Export the resource twice.
  406. exported = {};
  407. provider().PrepareSendToParent(to_send, &exported, context_provider());
  408. {
  409. // Return the resource the first time, marked as lost.
  410. std::vector<ReturnedResource> returned;
  411. returned.emplace_back();
  412. returned.back().id = exported[0].id;
  413. returned.back().count = 1;
  414. returned.back().lost = true;
  415. provider().ReceiveReturnsFromParent(std::move(returned));
  416. }
  417. {
  418. // Return a second time, not lost. The first lost signal should not be lost.
  419. std::vector<ReturnedResource> returned;
  420. returned.emplace_back();
  421. returned.back().id = exported[0].id;
  422. returned.back().count = 1;
  423. returned.back().lost = false;
  424. EXPECT_CALL(release, Released(_, true));
  425. provider().ReceiveReturnsFromParent(std::move(returned));
  426. }
  427. }
  428. TEST_P(ClientResourceProviderTest, ReturnedSyncTokensArePassedToClient) {
  429. // SyncTokens are gpu-only.
  430. if (!use_gpu())
  431. return;
  432. MockReleaseCallback release;
  433. auto* sii = context_provider()->SharedImageInterface();
  434. gpu::Mailbox mailbox = sii->CreateSharedImage(
  435. ResourceFormat::RGBA_8888, gfx::Size(1, 1), gfx::ColorSpace(),
  436. kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType,
  437. gpu::SHARED_IMAGE_USAGE_GLES2 | gpu::SHARED_IMAGE_USAGE_DISPLAY,
  438. gpu::kNullSurfaceHandle);
  439. gpu::SyncToken sync_token = sii->GenUnverifiedSyncToken();
  440. constexpr gfx::Size size(64, 64);
  441. auto tran = TransferableResource::MakeGL(mailbox, GL_LINEAR, GL_TEXTURE_2D,
  442. sync_token, size,
  443. false /* is_overlay_candidate */);
  444. ResourceId resource = provider().ImportResource(
  445. tran, base::BindOnce(&MockReleaseCallback::Released,
  446. base::Unretained(&release)));
  447. EXPECT_TRUE(tran.mailbox_holder.sync_token.HasData());
  448. // All the logic below assumes that the sync token releases are all positive.
  449. EXPECT_LT(0u, tran.mailbox_holder.sync_token.release_count());
  450. // Transfer the resource, expect the sync points to be consistent.
  451. std::vector<TransferableResource> list;
  452. provider().PrepareSendToParent({resource}, &list, context_provider());
  453. ASSERT_EQ(1u, list.size());
  454. EXPECT_LE(sync_token.release_count(),
  455. list[0].mailbox_holder.sync_token.release_count());
  456. EXPECT_EQ(0, memcmp(mailbox.name, list[0].mailbox_holder.mailbox.name,
  457. sizeof(mailbox.name)));
  458. // Make a new texture id from the mailbox.
  459. context_provider()->ContextGL()->WaitSyncTokenCHROMIUM(
  460. list[0].mailbox_holder.sync_token.GetConstData());
  461. unsigned other_texture =
  462. context_provider()->ContextGL()->CreateAndTexStorage2DSharedImageCHROMIUM(
  463. mailbox.name);
  464. // Then delete it and make a new SyncToken.
  465. context_provider()->ContextGL()->DeleteTextures(1, &other_texture);
  466. context_provider()->ContextGL()->GenSyncTokenCHROMIUM(
  467. list[0].mailbox_holder.sync_token.GetData());
  468. EXPECT_TRUE(list[0].mailbox_holder.sync_token.HasData());
  469. // Receive the resource, then delete it, expect the SyncTokens to be
  470. // consistent.
  471. provider().ReceiveReturnsFromParent(
  472. TransferableResource::ReturnResources(list));
  473. gpu::SyncToken returned_sync_token;
  474. EXPECT_CALL(release, Released(_, false))
  475. .WillOnce(testing::SaveArg<0>(&returned_sync_token));
  476. provider().RemoveImportedResource(resource);
  477. EXPECT_GE(returned_sync_token.release_count(),
  478. list[0].mailbox_holder.sync_token.release_count());
  479. }
  480. TEST_P(ClientResourceProviderTest, LostResourcesAreReturnedLost) {
  481. MockReleaseCallback release;
  482. TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 15);
  483. ResourceId resource = provider().ImportResource(
  484. tran, base::BindOnce(&MockReleaseCallback::Released,
  485. base::Unretained(&release)));
  486. // Transfer the resource to the parent.
  487. std::vector<TransferableResource> list;
  488. provider().PrepareSendToParent({resource}, &list, context_provider());
  489. EXPECT_EQ(1u, list.size());
  490. // Receive it back marked lost.
  491. std::vector<ReturnedResource> returned_to_child;
  492. returned_to_child.push_back(list[0].ToReturnedResource());
  493. returned_to_child.back().lost = true;
  494. provider().ReceiveReturnsFromParent(std::move(returned_to_child));
  495. // Delete the resource in the child. Expect the resource to be lost.
  496. EXPECT_CALL(release, Released(_, true));
  497. provider().RemoveImportedResource(resource);
  498. }
  499. TEST_P(ClientResourceProviderTest, ShutdownLosesExportedResources) {
  500. MockReleaseCallback release;
  501. TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 15);
  502. ResourceId resource = provider().ImportResource(
  503. tran, base::BindOnce(&MockReleaseCallback::Released,
  504. base::Unretained(&release)));
  505. // Transfer the resource to the parent.
  506. std::vector<TransferableResource> list;
  507. provider().PrepareSendToParent({resource}, &list, context_provider());
  508. EXPECT_EQ(1u, list.size());
  509. // Remove it in the ClientResourceProvider, but since it's exported it's not
  510. // returned yet.
  511. provider().RemoveImportedResource(resource);
  512. // Destroy the ClientResourceProvider, the resource is returned lost.
  513. EXPECT_CALL(release, Released(_, true));
  514. DestroyProvider();
  515. }
  516. TEST_P(ClientResourceProviderTest, ReleaseExportedResources) {
  517. MockReleaseCallback release;
  518. TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 15);
  519. ResourceId resource = provider().ImportResource(
  520. tran, base::BindOnce(&MockReleaseCallback::Released,
  521. base::Unretained(&release)));
  522. // Transfer the resource to the parent.
  523. std::vector<TransferableResource> list;
  524. provider().PrepareSendToParent({resource}, &list, context_provider());
  525. EXPECT_EQ(1u, list.size());
  526. // Remove it in the ClientResourceProvider, but since it's exported it's not
  527. // returned yet.
  528. provider().RemoveImportedResource(resource);
  529. // Drop any exported resources. They are returned lost for gpu compositing,
  530. // since gpu resources are modified (in their metadata) while being used by
  531. // the parent.
  532. EXPECT_CALL(release, Released(_, use_gpu()));
  533. provider().ReleaseAllExportedResources(use_gpu());
  534. EXPECT_CALL(release, Released(_, _)).Times(0);
  535. }
  536. TEST_P(ClientResourceProviderTest, ReleaseExportedResourcesThenRemove) {
  537. MockReleaseCallback release;
  538. TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 15);
  539. ResourceId resource = provider().ImportResource(
  540. tran, base::BindOnce(&MockReleaseCallback::Released,
  541. base::Unretained(&release)));
  542. // Transfer the resource to the parent.
  543. std::vector<TransferableResource> list;
  544. provider().PrepareSendToParent({resource}, &list, context_provider());
  545. EXPECT_EQ(1u, list.size());
  546. // Drop any exported resources. They are now considered lost for gpu
  547. // compositing, since gpu resources are modified (in their metadata) while
  548. // being used by the parent.
  549. provider().ReleaseAllExportedResources(use_gpu());
  550. EXPECT_CALL(release, Released(_, use_gpu()));
  551. // Remove it in the ClientResourceProvider, it was exported so wouldn't be
  552. // released here, except that we dropped the export above.
  553. provider().RemoveImportedResource(resource);
  554. EXPECT_CALL(release, Released(_, _)).Times(0);
  555. }
  556. TEST_P(ClientResourceProviderTest, ReleaseMultipleResources) {
  557. MockReleaseCallback release;
  558. // Make 5 resources, put them in a non-sorted order.
  559. ResourceId resources[5];
  560. for (int i = 0; i < 5; ++i) {
  561. TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 1 + i);
  562. resources[i] = provider().ImportResource(
  563. tran, base::BindOnce(&MockReleaseCallback::ReleasedWithId,
  564. base::Unretained(&release), ResourceId(i)));
  565. }
  566. // Transfer some resources to the parent, but not in the sorted order.
  567. std::vector<TransferableResource> list;
  568. provider().PrepareSendToParent({resources[2], resources[0], resources[4]},
  569. &list, context_provider());
  570. EXPECT_EQ(3u, list.size());
  571. // Receive them back. Since these are not in the same order they were
  572. // inserted originally, we verify the ClientResourceProvider can handle
  573. // resources being returned (in a group) that are not at the front/back
  574. // of its internal storage. IOW This shouldn't crash or corrupt state.
  575. std::vector<ReturnedResource> returned_to_child;
  576. returned_to_child.push_back(list[0].ToReturnedResource());
  577. returned_to_child.push_back(list[1].ToReturnedResource());
  578. returned_to_child.push_back(list[2].ToReturnedResource());
  579. provider().ReceiveReturnsFromParent(std::move(returned_to_child));
  580. // Remove them from the ClientResourceProvider, they should be returned as
  581. // they're no longer exported.
  582. EXPECT_CALL(release, ReleasedWithId(kInvalidResourceId, _, false));
  583. provider().RemoveImportedResource(resources[0]);
  584. EXPECT_CALL(release, ReleasedWithId(ResourceId(2), _, false));
  585. provider().RemoveImportedResource(resources[2]);
  586. EXPECT_CALL(release, ReleasedWithId(ResourceId(4), _, false));
  587. provider().RemoveImportedResource(resources[4]);
  588. // These were never exported.
  589. EXPECT_CALL(release, ReleasedWithId(ResourceId(1), _, false));
  590. EXPECT_CALL(release, ReleasedWithId(ResourceId(3), _, false));
  591. provider().RemoveImportedResource(resources[1]);
  592. provider().RemoveImportedResource(resources[3]);
  593. EXPECT_CALL(release, Released(_, false)).Times(0);
  594. }
  595. TEST_P(ClientResourceProviderTest, ReleaseMultipleResourcesBeforeReturn) {
  596. MockReleaseCallback release;
  597. // Make 5 resources, put them in a non-sorted order.
  598. ResourceId resources[5];
  599. for (int i = 0; i < 5; ++i) {
  600. TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 1 + i);
  601. resources[i] = provider().ImportResource(
  602. tran, base::BindOnce(&MockReleaseCallback::ReleasedWithId,
  603. base::Unretained(&release), ResourceId(i)));
  604. }
  605. // Transfer some resources to the parent, but not in the sorted order.
  606. std::vector<TransferableResource> list;
  607. provider().PrepareSendToParent({resources[2], resources[0], resources[4]},
  608. &list, context_provider());
  609. EXPECT_EQ(3u, list.size());
  610. // Remove the exported resources from the ClientResourceProvider, they should
  611. // not yet be returned, since they are exported.
  612. provider().RemoveImportedResource(resources[0]);
  613. provider().RemoveImportedResource(resources[2]);
  614. provider().RemoveImportedResource(resources[4]);
  615. // Receive them back now. Since these are not in the same order they were
  616. // inserted originally, we verify the ClientResourceProvider can handle
  617. // resources being returned (in a group) that are not at the front/back
  618. // of its internal storage. IOW This shouldn't crash or corrupt state.
  619. std::vector<ReturnedResource> returned_to_child;
  620. returned_to_child.push_back(list[0].ToReturnedResource());
  621. returned_to_child.push_back(list[1].ToReturnedResource());
  622. returned_to_child.push_back(list[2].ToReturnedResource());
  623. // The resources are returned immediately since they were previously removed.
  624. EXPECT_CALL(release, ReleasedWithId(kInvalidResourceId, _, false));
  625. EXPECT_CALL(release, ReleasedWithId(ResourceId(2), _, false));
  626. EXPECT_CALL(release, ReleasedWithId(ResourceId(4), _, false));
  627. provider().ReceiveReturnsFromParent(std::move(returned_to_child));
  628. // These were never exported.
  629. EXPECT_CALL(release, ReleasedWithId(ResourceId(1), _, false));
  630. EXPECT_CALL(release, ReleasedWithId(ResourceId(3), _, false));
  631. provider().RemoveImportedResource(resources[1]);
  632. provider().RemoveImportedResource(resources[3]);
  633. EXPECT_CALL(release, Released(_, false)).Times(0);
  634. }
  635. TEST_P(ClientResourceProviderTest, ReturnDuplicateResourceBeforeRemove) {
  636. MockReleaseCallback release;
  637. // Make 5 resources, put them in a non-sorted order.
  638. ResourceId resources[5];
  639. for (int i = 0; i < 5; ++i) {
  640. TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 1 + i);
  641. resources[i] = provider().ImportResource(
  642. tran, base::BindOnce(&MockReleaseCallback::ReleasedWithId,
  643. base::Unretained(&release), ResourceId(i)));
  644. }
  645. // Transfer a resource to the parent, do it twice.
  646. std::vector<TransferableResource> list;
  647. provider().PrepareSendToParent({resources[2]}, &list, context_provider());
  648. list.clear();
  649. provider().PrepareSendToParent({resources[2]}, &list, context_provider());
  650. // Receive the resource back. It's possible that the parent may return
  651. // the same ResourceId multiple times in the same message, which we test
  652. // for here.
  653. std::vector<ReturnedResource> returned_to_child;
  654. returned_to_child.push_back(list[0].ToReturnedResource());
  655. returned_to_child.push_back(list[0].ToReturnedResource());
  656. provider().ReceiveReturnsFromParent(std::move(returned_to_child));
  657. // Remove it from the ClientResourceProvider, it should be returned as
  658. // it's no longer exported.
  659. EXPECT_CALL(release, ReleasedWithId(ResourceId(2), _, false));
  660. provider().RemoveImportedResource(resources[2]);
  661. // These were never exported.
  662. EXPECT_CALL(release, ReleasedWithId(kInvalidResourceId, _, false));
  663. EXPECT_CALL(release, ReleasedWithId(ResourceId(1), _, false));
  664. EXPECT_CALL(release, ReleasedWithId(ResourceId(3), _, false));
  665. EXPECT_CALL(release, ReleasedWithId(ResourceId(4), _, false));
  666. provider().RemoveImportedResource(resources[0]);
  667. provider().RemoveImportedResource(resources[1]);
  668. provider().RemoveImportedResource(resources[3]);
  669. provider().RemoveImportedResource(resources[4]);
  670. EXPECT_CALL(release, Released(_, false)).Times(0);
  671. }
  672. TEST_P(ClientResourceProviderTest, ReturnDuplicateResourceAfterRemove) {
  673. MockReleaseCallback release;
  674. // Make 5 resources, put them in a non-sorted order.
  675. ResourceId resources[5];
  676. for (int i = 0; i < 5; ++i) {
  677. TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 1 + i);
  678. resources[i] = provider().ImportResource(
  679. tran, base::BindOnce(&MockReleaseCallback::ReleasedWithId,
  680. base::Unretained(&release), ResourceId(i)));
  681. }
  682. // Transfer a resource to the parent, do it twice.
  683. std::vector<TransferableResource> list;
  684. provider().PrepareSendToParent({resources[2]}, &list, context_provider());
  685. list.clear();
  686. provider().PrepareSendToParent({resources[2]}, &list, context_provider());
  687. // Remove it from the ClientResourceProvider, it should not be returned yet
  688. // as it's still exported.
  689. provider().RemoveImportedResource(resources[2]);
  690. // Receive the resource back. It's possible that the parent may return
  691. // the same ResourceId multiple times in the same message, which we test
  692. // for here.
  693. std::vector<ReturnedResource> returned_to_child;
  694. returned_to_child.push_back(list[0].ToReturnedResource());
  695. returned_to_child.push_back(list[0].ToReturnedResource());
  696. // Once no longer exported, since it was removed earlier, it will be returned
  697. // immediately.
  698. EXPECT_CALL(release, ReleasedWithId(ResourceId(2), _, false));
  699. provider().ReceiveReturnsFromParent(std::move(returned_to_child));
  700. // These were never exported.
  701. EXPECT_CALL(release, ReleasedWithId(kInvalidResourceId, _, false));
  702. EXPECT_CALL(release, ReleasedWithId(ResourceId(1), _, false));
  703. EXPECT_CALL(release, ReleasedWithId(ResourceId(3), _, false));
  704. EXPECT_CALL(release, ReleasedWithId(ResourceId(4), _, false));
  705. provider().RemoveImportedResource(resources[0]);
  706. provider().RemoveImportedResource(resources[1]);
  707. provider().RemoveImportedResource(resources[3]);
  708. provider().RemoveImportedResource(resources[4]);
  709. EXPECT_CALL(release, Released(_, false)).Times(0);
  710. }
  711. } // namespace
  712. } // namespace viz