gpu_channel_unittest.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. // Copyright (c) 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 "gpu/ipc/service/gpu_channel.h"
  5. #include <stdint.h>
  6. #include "base/run_loop.h"
  7. #include "base/test/test_simple_task_runner.h"
  8. #include "build/build_config.h"
  9. #include "gpu/ipc/common/command_buffer_id.h"
  10. #include "gpu/ipc/common/gpu_channel.mojom.h"
  11. #include "gpu/ipc/service/gpu_channel_manager.h"
  12. #include "gpu/ipc/service/gpu_channel_test_common.h"
  13. namespace gpu {
  14. class GpuChannelTest : public GpuChannelTestCommon {
  15. public:
  16. GpuChannelTest() : GpuChannelTestCommon(true /* use_stub_bindings */) {}
  17. ~GpuChannelTest() override = default;
  18. };
  19. #if BUILDFLAG(IS_WIN)
  20. const SurfaceHandle kFakeSurfaceHandle = reinterpret_cast<SurfaceHandle>(1);
  21. #else
  22. const SurfaceHandle kFakeSurfaceHandle = 1;
  23. #endif
  24. TEST_F(GpuChannelTest, CreateViewCommandBufferAllowed) {
  25. int32_t kClientId = 1;
  26. bool is_gpu_host = true;
  27. GpuChannel* channel = CreateChannel(kClientId, is_gpu_host);
  28. ASSERT_TRUE(channel);
  29. SurfaceHandle surface_handle = kFakeSurfaceHandle;
  30. DCHECK_NE(surface_handle, kNullSurfaceHandle);
  31. int32_t kRouteId =
  32. static_cast<int32_t>(GpuChannelReservedRoutes::kMaxValue) + 1;
  33. auto init_params = mojom::CreateCommandBufferParams::New();
  34. init_params->surface_handle = surface_handle;
  35. init_params->share_group_id = MSG_ROUTING_NONE;
  36. init_params->stream_id = 0;
  37. init_params->stream_priority = SchedulingPriority::kNormal;
  38. init_params->attribs = ContextCreationAttribs();
  39. init_params->active_url = GURL();
  40. gpu::ContextResult result = gpu::ContextResult::kSuccess;
  41. gpu::Capabilities capabilities;
  42. CreateCommandBuffer(*channel, std::move(init_params), kRouteId,
  43. GetSharedMemoryRegion(), &result, &capabilities);
  44. EXPECT_EQ(result, gpu::ContextResult::kSuccess);
  45. CommandBufferStub* stub = channel->LookupCommandBuffer(kRouteId);
  46. ASSERT_TRUE(stub);
  47. }
  48. TEST_F(GpuChannelTest, CreateViewCommandBufferDisallowed) {
  49. int32_t kClientId = 1;
  50. bool is_gpu_host = false;
  51. GpuChannel* channel = CreateChannel(kClientId, is_gpu_host);
  52. ASSERT_TRUE(channel);
  53. SurfaceHandle surface_handle = kFakeSurfaceHandle;
  54. DCHECK_NE(surface_handle, kNullSurfaceHandle);
  55. int32_t kRouteId =
  56. static_cast<int32_t>(GpuChannelReservedRoutes::kMaxValue) + 1;
  57. auto init_params = mojom::CreateCommandBufferParams::New();
  58. init_params->surface_handle = surface_handle;
  59. init_params->share_group_id = MSG_ROUTING_NONE;
  60. init_params->stream_id = 0;
  61. init_params->stream_priority = SchedulingPriority::kNormal;
  62. init_params->attribs = ContextCreationAttribs();
  63. init_params->active_url = GURL();
  64. gpu::ContextResult result = gpu::ContextResult::kSuccess;
  65. gpu::Capabilities capabilities;
  66. CreateCommandBuffer(*channel, std::move(init_params), kRouteId,
  67. GetSharedMemoryRegion(), &result, &capabilities);
  68. EXPECT_EQ(result, gpu::ContextResult::kFatalFailure);
  69. CommandBufferStub* stub = channel->LookupCommandBuffer(kRouteId);
  70. EXPECT_FALSE(stub);
  71. }
  72. TEST_F(GpuChannelTest, CreateOffscreenCommandBuffer) {
  73. int32_t kClientId = 1;
  74. GpuChannel* channel = CreateChannel(kClientId, true);
  75. ASSERT_TRUE(channel);
  76. int32_t kRouteId =
  77. static_cast<int32_t>(GpuChannelReservedRoutes::kMaxValue) + 1;
  78. auto init_params = mojom::CreateCommandBufferParams::New();
  79. init_params->surface_handle = kNullSurfaceHandle;
  80. init_params->share_group_id = MSG_ROUTING_NONE;
  81. init_params->stream_id = 0;
  82. init_params->stream_priority = SchedulingPriority::kNormal;
  83. init_params->attribs = ContextCreationAttribs();
  84. init_params->active_url = GURL();
  85. gpu::ContextResult result = gpu::ContextResult::kSuccess;
  86. gpu::Capabilities capabilities;
  87. CreateCommandBuffer(*channel, std::move(init_params), kRouteId,
  88. GetSharedMemoryRegion(), &result, &capabilities);
  89. EXPECT_EQ(result, gpu::ContextResult::kSuccess);
  90. CommandBufferStub* stub = channel->LookupCommandBuffer(kRouteId);
  91. EXPECT_TRUE(stub);
  92. }
  93. TEST_F(GpuChannelTest, IncompatibleStreamIds) {
  94. int32_t kClientId = 1;
  95. GpuChannel* channel = CreateChannel(kClientId, true);
  96. ASSERT_TRUE(channel);
  97. // Create first context.
  98. int32_t kRouteId1 =
  99. static_cast<int32_t>(GpuChannelReservedRoutes::kMaxValue) + 1;
  100. int32_t kStreamId1 = 1;
  101. auto init_params = mojom::CreateCommandBufferParams::New();
  102. init_params->surface_handle = kNullSurfaceHandle;
  103. init_params->share_group_id = MSG_ROUTING_NONE;
  104. init_params->stream_id = kStreamId1;
  105. init_params->stream_priority = SchedulingPriority::kNormal;
  106. auto init_params2 = init_params.Clone();
  107. gpu::ContextResult result = gpu::ContextResult::kSuccess;
  108. gpu::Capabilities capabilities;
  109. CreateCommandBuffer(*channel, std::move(init_params), kRouteId1,
  110. GetSharedMemoryRegion(), &result, &capabilities);
  111. EXPECT_EQ(result, gpu::ContextResult::kSuccess);
  112. CommandBufferStub* stub = channel->LookupCommandBuffer(kRouteId1);
  113. EXPECT_TRUE(stub);
  114. // Create second context in same share group but different stream.
  115. int32_t kRouteId2 = kRouteId1 + 1;
  116. int32_t kStreamId2 = 2;
  117. init_params2->share_group_id = kRouteId1;
  118. init_params2->stream_id = kStreamId2;
  119. init_params2->stream_priority = SchedulingPriority::kNormal;
  120. CreateCommandBuffer(*channel, std::move(init_params2), kRouteId2,
  121. GetSharedMemoryRegion(), &result, &capabilities);
  122. EXPECT_EQ(result, gpu::ContextResult::kFatalFailure);
  123. stub = channel->LookupCommandBuffer(kRouteId2);
  124. EXPECT_FALSE(stub);
  125. }
  126. TEST_F(GpuChannelTest, CreateFailsIfSharedContextIsLost) {
  127. int32_t kClientId = 1;
  128. GpuChannel* channel = CreateChannel(kClientId, false);
  129. ASSERT_TRUE(channel);
  130. // Create first context, we will share this one.
  131. int32_t kSharedRouteId =
  132. static_cast<int32_t>(GpuChannelReservedRoutes::kMaxValue) + 1;
  133. {
  134. SCOPED_TRACE("kSharedRouteId");
  135. auto init_params = mojom::CreateCommandBufferParams::New();
  136. init_params->surface_handle = kNullSurfaceHandle;
  137. init_params->share_group_id = MSG_ROUTING_NONE;
  138. init_params->stream_id = 0;
  139. init_params->stream_priority = SchedulingPriority::kNormal;
  140. init_params->attribs = ContextCreationAttribs();
  141. init_params->active_url = GURL();
  142. gpu::ContextResult result = gpu::ContextResult::kSuccess;
  143. gpu::Capabilities capabilities;
  144. CreateCommandBuffer(*channel, std::move(init_params), kSharedRouteId,
  145. GetSharedMemoryRegion(), &result, &capabilities);
  146. EXPECT_EQ(result, gpu::ContextResult::kSuccess);
  147. }
  148. EXPECT_TRUE(channel->LookupCommandBuffer(kSharedRouteId));
  149. // This context shares with the first one, this should be possible.
  150. int32_t kFriendlyRouteId = kSharedRouteId + 1;
  151. {
  152. SCOPED_TRACE("kFriendlyRouteId");
  153. auto init_params = mojom::CreateCommandBufferParams::New();
  154. init_params->surface_handle = kNullSurfaceHandle;
  155. init_params->share_group_id = kSharedRouteId;
  156. init_params->stream_id = 0;
  157. init_params->stream_priority = SchedulingPriority::kNormal;
  158. init_params->attribs = ContextCreationAttribs();
  159. init_params->active_url = GURL();
  160. gpu::ContextResult result = gpu::ContextResult::kSuccess;
  161. gpu::Capabilities capabilities;
  162. CreateCommandBuffer(*channel, std::move(init_params), kFriendlyRouteId,
  163. GetSharedMemoryRegion(), &result, &capabilities);
  164. EXPECT_EQ(result, gpu::ContextResult::kSuccess);
  165. }
  166. EXPECT_TRUE(channel->LookupCommandBuffer(kFriendlyRouteId));
  167. // The shared context is lost.
  168. channel->LookupCommandBuffer(kSharedRouteId)->MarkContextLost();
  169. // Meanwhile another context is being made pointing to the shared one. This
  170. // should fail.
  171. int32_t kAnotherRouteId = kFriendlyRouteId + 1;
  172. {
  173. SCOPED_TRACE("kAnotherRouteId");
  174. auto init_params = mojom::CreateCommandBufferParams::New();
  175. init_params->surface_handle = kNullSurfaceHandle;
  176. init_params->share_group_id = kSharedRouteId;
  177. init_params->stream_id = 0;
  178. init_params->stream_priority = SchedulingPriority::kNormal;
  179. init_params->attribs = ContextCreationAttribs();
  180. init_params->active_url = GURL();
  181. gpu::ContextResult result = gpu::ContextResult::kSuccess;
  182. gpu::Capabilities capabilities;
  183. CreateCommandBuffer(*channel, std::move(init_params), kAnotherRouteId,
  184. GetSharedMemoryRegion(), &result, &capabilities);
  185. EXPECT_EQ(result, gpu::ContextResult::kTransientFailure);
  186. }
  187. EXPECT_FALSE(channel->LookupCommandBuffer(kAnotherRouteId));
  188. // The lost context is still around though (to verify the failure happened due
  189. // to the shared context being lost, not due to it being deleted).
  190. EXPECT_TRUE(channel->LookupCommandBuffer(kSharedRouteId));
  191. // Destroy the command buffers we initialized before destoying GL.
  192. channel->DestroyCommandBuffer(kFriendlyRouteId);
  193. channel->DestroyCommandBuffer(kSharedRouteId);
  194. }
  195. class GpuChannelExitForContextLostTest : public GpuChannelTestCommon {
  196. public:
  197. GpuChannelExitForContextLostTest()
  198. : GpuChannelTestCommon({EXIT_ON_CONTEXT_LOST} /* enabled_workarounds */,
  199. true /* use_stub_bindings */) {}
  200. };
  201. TEST_F(GpuChannelExitForContextLostTest,
  202. CreateFailsDuringLostContextShutdown_1) {
  203. int32_t kClientId = 1;
  204. GpuChannel* channel = CreateChannel(kClientId, false);
  205. ASSERT_TRUE(channel);
  206. // Put channel manager into shutdown state.
  207. channel_manager()->OnContextLost(false /* synthetic_loss */);
  208. // Calling OnContextLost() above may destroy the gpu channel via post task.
  209. // Ensure that post task has happened.
  210. base::RunLoop().RunUntilIdle();
  211. // If the channel is destroyed, then skip the test.
  212. if (!channel_manager()->LookupChannel(kClientId))
  213. return;
  214. // Try to create a context.
  215. int32_t kRouteId =
  216. static_cast<int32_t>(GpuChannelReservedRoutes::kMaxValue) + 1;
  217. auto init_params = mojom::CreateCommandBufferParams::New();
  218. init_params->surface_handle = kNullSurfaceHandle;
  219. init_params->share_group_id = MSG_ROUTING_NONE;
  220. init_params->stream_id = 0;
  221. init_params->stream_priority = SchedulingPriority::kNormal;
  222. init_params->attribs = ContextCreationAttribs();
  223. init_params->active_url = GURL();
  224. gpu::ContextResult result = gpu::ContextResult::kSuccess;
  225. gpu::Capabilities capabilities;
  226. CreateCommandBuffer(*channel, std::move(init_params), kRouteId,
  227. GetSharedMemoryRegion(), &result, &capabilities);
  228. EXPECT_EQ(result, gpu::ContextResult::kTransientFailure);
  229. EXPECT_FALSE(channel->LookupCommandBuffer(kRouteId));
  230. }
  231. TEST_F(GpuChannelExitForContextLostTest,
  232. CreateFailsDuringLostContextShutdown_2) {
  233. // Put channel manager into shutdown state. Do this before creating a channel,
  234. // as doing this may destroy any active channels.
  235. channel_manager()->OnContextLost(false /* synthetic_loss */);
  236. int32_t kClientId = 1;
  237. GpuChannel* channel = CreateChannel(kClientId, false);
  238. ASSERT_TRUE(channel);
  239. // Try to create a context.
  240. int32_t kRouteId =
  241. static_cast<int32_t>(GpuChannelReservedRoutes::kMaxValue) + 1;
  242. auto init_params = mojom::CreateCommandBufferParams::New();
  243. init_params->surface_handle = kNullSurfaceHandle;
  244. init_params->share_group_id = MSG_ROUTING_NONE;
  245. init_params->stream_id = 0;
  246. init_params->stream_priority = SchedulingPriority::kNormal;
  247. init_params->attribs = ContextCreationAttribs();
  248. init_params->active_url = GURL();
  249. gpu::ContextResult result = gpu::ContextResult::kSuccess;
  250. gpu::Capabilities capabilities;
  251. CreateCommandBuffer(*channel, std::move(init_params), kRouteId,
  252. GetSharedMemoryRegion(), &result, &capabilities);
  253. EXPECT_EQ(result, gpu::ContextResult::kTransientFailure);
  254. EXPECT_FALSE(channel->LookupCommandBuffer(kRouteId));
  255. }
  256. } // namespace gpu