gpu_client.cc 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. // Copyright 2016 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/host/gpu_client.h"
  5. #include <utility>
  6. #include "base/bind.h"
  7. #include "base/metrics/histogram_macros.h"
  8. #include "base/numerics/checked_math.h"
  9. #include "build/chromeos_buildflags.h"
  10. #include "components/viz/host/gpu_host_impl.h"
  11. #include "components/viz/host/host_gpu_memory_buffer_manager.h"
  12. #include "gpu/ipc/client/gpu_channel_host.h"
  13. #include "gpu/ipc/common/gpu_memory_buffer_impl.h"
  14. #include "gpu/ipc/common/gpu_memory_buffer_impl_shared_memory.h"
  15. #include "services/viz/privileged/mojom/gl/gpu_service.mojom.h"
  16. namespace viz {
  17. namespace {
  18. bool IsSizeValid(const gfx::Size& size) {
  19. base::CheckedNumeric<int> bytes = size.width();
  20. bytes *= size.height();
  21. return bytes.IsValid();
  22. }
  23. } // namespace
  24. GpuClient::GpuClient(std::unique_ptr<GpuClientDelegate> delegate,
  25. int client_id,
  26. uint64_t client_tracing_id,
  27. scoped_refptr<base::SingleThreadTaskRunner> task_runner)
  28. : delegate_(std::move(delegate)),
  29. client_id_(client_id),
  30. client_tracing_id_(client_tracing_id),
  31. task_runner_(std::move(task_runner)) {
  32. DCHECK(delegate_);
  33. gpu_receivers_.set_disconnect_handler(
  34. base::BindRepeating(&GpuClient::OnError, base::Unretained(this),
  35. ErrorReason::kConnectionLost));
  36. }
  37. GpuClient::~GpuClient() {
  38. DCHECK(task_runner_->RunsTasksInCurrentSequence());
  39. gpu_receivers_.Clear();
  40. OnError(ErrorReason::kInDestructor);
  41. }
  42. void GpuClient::Add(mojo::PendingReceiver<mojom::Gpu> receiver) {
  43. DCHECK(task_runner_->RunsTasksInCurrentSequence());
  44. gpu_receivers_.Add(this, std::move(receiver));
  45. }
  46. void GpuClient::OnError(ErrorReason reason) {
  47. DCHECK(task_runner_->RunsTasksInCurrentSequence());
  48. ClearCallback();
  49. if (gpu_receivers_.empty() && delegate_) {
  50. if (auto* gpu_memory_buffer_manager =
  51. delegate_->GetGpuMemoryBufferManager()) {
  52. gpu_memory_buffer_manager->DestroyAllGpuMemoryBufferForClient(client_id_);
  53. }
  54. }
  55. if (reason == ErrorReason::kConnectionLost && connection_error_handler_)
  56. std::move(connection_error_handler_).Run(this);
  57. }
  58. void GpuClient::PreEstablishGpuChannel() {
  59. if (!task_runner_->RunsTasksInCurrentSequence()) {
  60. task_runner_->PostTask(FROM_HERE,
  61. base::BindOnce(&GpuClient::EstablishGpuChannel,
  62. weak_factory_.GetWeakPtr(),
  63. EstablishGpuChannelCallback()));
  64. return;
  65. }
  66. EstablishGpuChannel(EstablishGpuChannelCallback());
  67. }
  68. void GpuClient::SetClientPid(base::ProcessId client_pid) {
  69. if (!task_runner_->RunsTasksInCurrentSequence()) {
  70. task_runner_->PostTask(
  71. FROM_HERE, base::BindOnce(&GpuClient::SetClientPid,
  72. weak_factory_.GetWeakPtr(), client_pid));
  73. return;
  74. }
  75. if (GpuHostImpl* gpu_host = delegate_->EnsureGpuHost())
  76. gpu_host->SetChannelClientPid(client_id_, client_pid);
  77. }
  78. void GpuClient::SetDiskCacheHandle(const gpu::GpuDiskCacheHandle& handle) {
  79. if (!task_runner_->RunsTasksInCurrentSequence()) {
  80. task_runner_->PostTask(FROM_HERE,
  81. base::BindOnce(&GpuClient::SetDiskCacheHandle,
  82. weak_factory_.GetWeakPtr(), handle));
  83. return;
  84. }
  85. if (GpuHostImpl* gpu_host = delegate_->EnsureGpuHost())
  86. gpu_host->SetChannelDiskCacheHandle(client_id_, handle);
  87. }
  88. void GpuClient::RemoveDiskCacheHandles() {
  89. if (!task_runner_->RunsTasksInCurrentSequence()) {
  90. task_runner_->PostTask(FROM_HERE,
  91. base::BindOnce(&GpuClient::RemoveDiskCacheHandles,
  92. weak_factory_.GetWeakPtr()));
  93. return;
  94. }
  95. if (GpuHostImpl* gpu_host = delegate_->EnsureGpuHost())
  96. gpu_host->RemoveChannelDiskCacheHandles(client_id_);
  97. }
  98. void GpuClient::SetConnectionErrorHandler(
  99. ConnectionErrorHandlerClosure connection_error_handler) {
  100. connection_error_handler_ = std::move(connection_error_handler);
  101. }
  102. base::WeakPtr<GpuClient> GpuClient::GetWeakPtr() {
  103. return weak_factory_.GetWeakPtr();
  104. }
  105. void GpuClient::OnEstablishGpuChannel(
  106. mojo::ScopedMessagePipeHandle channel_handle,
  107. const gpu::GPUInfo& gpu_info,
  108. const gpu::GpuFeatureInfo& gpu_feature_info,
  109. GpuHostImpl::EstablishChannelStatus status) {
  110. DCHECK_EQ(channel_handle.is_valid(),
  111. status == GpuHostImpl::EstablishChannelStatus::kSuccess);
  112. gpu_channel_requested_ = false;
  113. EstablishGpuChannelCallback callback = std::move(callback_);
  114. if (status == GpuHostImpl::EstablishChannelStatus::kGpuHostInvalid) {
  115. // GPU process may have crashed or been killed. Try again.
  116. EstablishGpuChannel(std::move(callback));
  117. return;
  118. }
  119. if (callback) {
  120. // A request is waiting.
  121. std::move(callback).Run(client_id_, std::move(channel_handle), gpu_info,
  122. gpu_feature_info);
  123. return;
  124. }
  125. if (status == GpuHostImpl::EstablishChannelStatus::kSuccess) {
  126. // This is the case we pre-establish a channel before a request arrives.
  127. // Cache the channel for a future request.
  128. channel_handle_ = std::move(channel_handle);
  129. gpu_info_ = gpu_info;
  130. gpu_feature_info_ = gpu_feature_info;
  131. }
  132. }
  133. void GpuClient::OnCreateGpuMemoryBuffer(gfx::GpuMemoryBufferId id,
  134. gfx::GpuMemoryBufferHandle handle) {
  135. auto it = pending_create_callbacks_.find(id);
  136. DCHECK(it != pending_create_callbacks_.end());
  137. CreateGpuMemoryBufferCallback callback = std::move(it->second);
  138. pending_create_callbacks_.erase(it);
  139. std::move(callback).Run(std::move(handle));
  140. }
  141. void GpuClient::ClearCallback() {
  142. if (!callback_)
  143. return;
  144. EstablishGpuChannelCallback callback = std::move(callback_);
  145. std::move(callback).Run(client_id_, mojo::ScopedMessagePipeHandle(),
  146. gpu::GPUInfo(), gpu::GpuFeatureInfo());
  147. }
  148. void GpuClient::EstablishGpuChannel(EstablishGpuChannelCallback callback) {
  149. DCHECK(task_runner_->RunsTasksInCurrentSequence());
  150. // At most one channel should be requested. So clear previous request first.
  151. ClearCallback();
  152. if (channel_handle_.is_valid()) {
  153. // If a channel has been pre-established and cached,
  154. // 1) if callback is valid, return it right away.
  155. // 2) if callback is empty, it's PreEstablishGpyChannel() being called
  156. // more than once, no need to do anything.
  157. if (callback) {
  158. std::move(callback).Run(client_id_, std::move(channel_handle_), gpu_info_,
  159. gpu_feature_info_);
  160. DCHECK(!channel_handle_.is_valid());
  161. }
  162. return;
  163. }
  164. GpuHostImpl* gpu_host = delegate_->EnsureGpuHost();
  165. if (!gpu_host) {
  166. if (callback) {
  167. std::move(callback).Run(client_id_, mojo::ScopedMessagePipeHandle(),
  168. gpu::GPUInfo(), gpu::GpuFeatureInfo());
  169. }
  170. return;
  171. }
  172. callback_ = std::move(callback);
  173. if (gpu_channel_requested_)
  174. return;
  175. gpu_channel_requested_ = true;
  176. const bool is_gpu_host = false;
  177. gpu_host->EstablishGpuChannel(
  178. client_id_, client_tracing_id_, is_gpu_host, false,
  179. base::BindOnce(&GpuClient::OnEstablishGpuChannel,
  180. weak_factory_.GetWeakPtr()));
  181. }
  182. #if BUILDFLAG(IS_CHROMEOS_ASH)
  183. void GpuClient::CreateJpegDecodeAccelerator(
  184. mojo::PendingReceiver<chromeos_camera::mojom::MjpegDecodeAccelerator>
  185. jda_receiver) {
  186. if (auto* gpu_host = delegate_->EnsureGpuHost()) {
  187. gpu_host->gpu_service()->CreateJpegDecodeAccelerator(
  188. std::move(jda_receiver));
  189. }
  190. }
  191. #endif // BUILDFLAG(IS_CHROMEOS_ASH)
  192. void GpuClient::CreateVideoEncodeAcceleratorProvider(
  193. mojo::PendingReceiver<media::mojom::VideoEncodeAcceleratorProvider>
  194. vea_provider_receiver) {
  195. if (auto* gpu_host = delegate_->EnsureGpuHost()) {
  196. gpu_host->gpu_service()->CreateVideoEncodeAcceleratorProvider(
  197. std::move(vea_provider_receiver));
  198. }
  199. }
  200. void GpuClient::CreateGpuMemoryBuffer(
  201. gfx::GpuMemoryBufferId id,
  202. const gfx::Size& size,
  203. gfx::BufferFormat format,
  204. gfx::BufferUsage usage,
  205. mojom::GpuMemoryBufferFactory::CreateGpuMemoryBufferCallback callback) {
  206. auto* gpu_memory_buffer_manager = delegate_->GetGpuMemoryBufferManager();
  207. if (pending_create_callbacks_.find(id) != pending_create_callbacks_.end()) {
  208. gpu_memory_buffer_factory_receivers_.ReportBadMessage(
  209. "GpuMemoryBufferId already in use");
  210. return;
  211. }
  212. if (!IsSizeValid(size)) {
  213. gpu_memory_buffer_factory_receivers_.ReportBadMessage("Invalid GMB size");
  214. return;
  215. }
  216. if (!gpu_memory_buffer_manager) {
  217. std::move(callback).Run(gfx::GpuMemoryBufferHandle());
  218. return;
  219. }
  220. pending_create_callbacks_[id] = std::move(callback);
  221. gpu_memory_buffer_manager->AllocateGpuMemoryBuffer(
  222. id, client_id_, size, format, usage, gpu::kNullSurfaceHandle,
  223. base::BindOnce(&GpuClient::OnCreateGpuMemoryBuffer,
  224. weak_factory_.GetWeakPtr(), id));
  225. }
  226. void GpuClient::DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id,
  227. const gpu::SyncToken& sync_token) {
  228. if (auto* gpu_memory_buffer_manager =
  229. delegate_->GetGpuMemoryBufferManager()) {
  230. gpu_memory_buffer_manager->DestroyGpuMemoryBuffer(id, client_id_,
  231. sync_token);
  232. }
  233. }
  234. void GpuClient::CopyGpuMemoryBuffer(
  235. gfx::GpuMemoryBufferHandle buffer_handle,
  236. base::UnsafeSharedMemoryRegion shared_memory,
  237. CopyGpuMemoryBufferCallback callback) {
  238. auto* gpu_memory_buffer_manager = delegate_->GetGpuMemoryBufferManager();
  239. if (!gpu_memory_buffer_manager) {
  240. std::move(callback).Run(false);
  241. return;
  242. }
  243. gpu_memory_buffer_manager->CopyGpuMemoryBufferAsync(
  244. std::move(buffer_handle), std::move(shared_memory), std::move(callback));
  245. }
  246. void GpuClient::CreateGpuMemoryBufferFactory(
  247. mojo::PendingReceiver<mojom::GpuMemoryBufferFactory> receiver) {
  248. gpu_memory_buffer_factory_receivers_.Add(this, std::move(receiver));
  249. }
  250. } // namespace viz