command_buffer_helper.cc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. // Copyright 2018 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 "media/gpu/command_buffer_helper.h"
  5. #include <utility>
  6. #include <vector>
  7. #include "base/logging.h"
  8. #include "base/memory/raw_ptr.h"
  9. #include "base/task/single_thread_task_runner.h"
  10. #include "base/threading/thread_checker.h"
  11. #include "build/build_config.h"
  12. #include "gpu/command_buffer/common/scheduling_priority.h"
  13. #include "gpu/command_buffer/service/decoder_context.h"
  14. #include "gpu/command_buffer/service/scheduler.h"
  15. #include "gpu/command_buffer/service/shared_image/shared_image_backing.h"
  16. #include "gpu/command_buffer/service/shared_image/shared_image_representation.h"
  17. #include "gpu/command_buffer/service/sync_point_manager.h"
  18. #include "gpu/ipc/service/command_buffer_stub.h"
  19. #include "gpu/ipc/service/gpu_channel.h"
  20. #include "gpu/ipc/service/gpu_channel_manager.h"
  21. #include "media/gpu/gles2_decoder_helper.h"
  22. #include "ui/gl/gl_context.h"
  23. #if BUILDFLAG(IS_WIN)
  24. #include "gpu/command_buffer/service/dxgi_shared_handle_manager.h"
  25. #endif
  26. namespace media {
  27. namespace {
  28. class CommandBufferHelperImpl
  29. : public CommandBufferHelper,
  30. public gpu::CommandBufferStub::DestructionObserver {
  31. public:
  32. explicit CommandBufferHelperImpl(gpu::CommandBufferStub* stub)
  33. : CommandBufferHelper(stub->channel()->task_runner()),
  34. stub_(stub),
  35. memory_tracker_(this),
  36. memory_type_tracker_(&memory_tracker_) {
  37. DVLOG(1) << __func__;
  38. DCHECK(stub_->channel()->task_runner()->BelongsToCurrentThread());
  39. stub_->AddDestructionObserver(this);
  40. wait_sequence_id_ = stub_->channel()->scheduler()->CreateSequence(
  41. #if BUILDFLAG(IS_MAC)
  42. // Workaround for crbug.com/1035750.
  43. // TODO(sandersd): Investigate whether there is a deeper scheduling
  44. // problem that can be resolved.
  45. gpu::SchedulingPriority::kHigh
  46. #else
  47. gpu::SchedulingPriority::kNormal
  48. #endif // BUILDFLAG(IS_MAC)
  49. ,
  50. stub_->channel()->task_runner());
  51. decoder_helper_ = GLES2DecoderHelper::Create(stub_->decoder_context());
  52. }
  53. CommandBufferHelperImpl(const CommandBufferHelperImpl&) = delete;
  54. CommandBufferHelperImpl& operator=(const CommandBufferHelperImpl&) = delete;
  55. gl::GLContext* GetGLContext() override {
  56. DVLOG(2) << __func__;
  57. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  58. if (!decoder_helper_)
  59. return nullptr;
  60. return decoder_helper_->GetGLContext();
  61. }
  62. gpu::SharedImageStub* GetSharedImageStub() override {
  63. return shared_image_stub();
  64. }
  65. // Const variant of above method for internal callers.
  66. gpu::SharedImageStub* shared_image_stub() const {
  67. if (!stub_)
  68. return nullptr;
  69. return stub_->channel()->shared_image_stub();
  70. }
  71. #if BUILDFLAG(IS_WIN)
  72. gpu::DXGISharedHandleManager* GetDXGISharedHandleManager() override {
  73. if (!stub_)
  74. return nullptr;
  75. return stub_->channel()
  76. ->gpu_channel_manager()
  77. ->shared_image_manager()
  78. ->dxgi_shared_handle_manager()
  79. .get();
  80. }
  81. #endif
  82. bool HasStub() override {
  83. DVLOG(4) << __func__;
  84. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  85. return stub_;
  86. }
  87. bool MakeContextCurrent() override {
  88. DVLOG(2) << __func__;
  89. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  90. return decoder_helper_ && decoder_helper_->MakeContextCurrent();
  91. }
  92. std::unique_ptr<gpu::SharedImageRepresentationFactoryRef> Register(
  93. std::unique_ptr<gpu::SharedImageBacking> backing) override {
  94. DVLOG(2) << __func__;
  95. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  96. return stub_->channel()
  97. ->gpu_channel_manager()
  98. ->shared_image_manager()
  99. ->Register(std::move(backing), &memory_type_tracker_);
  100. }
  101. gpu::TextureBase* GetTexture(GLuint service_id) const override {
  102. DVLOG(2) << __func__ << "(" << service_id << ")";
  103. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  104. DCHECK(stub_->decoder_context()->GetGLContext()->IsCurrent(nullptr));
  105. DCHECK(textures_.count(service_id));
  106. return textures_.at(service_id)->GetTextureBase();
  107. }
  108. GLuint CreateTexture(GLenum target,
  109. GLenum internal_format,
  110. GLsizei width,
  111. GLsizei height,
  112. GLenum format,
  113. GLenum type) override {
  114. DVLOG(2) << __func__;
  115. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  116. DCHECK(stub_->decoder_context()->GetGLContext()->IsCurrent(nullptr));
  117. std::unique_ptr<gpu::gles2::AbstractTexture> texture =
  118. decoder_helper_->CreateTexture(target, internal_format, width, height,
  119. format, type);
  120. GLuint service_id = texture->service_id();
  121. textures_[service_id] = std::move(texture);
  122. return service_id;
  123. }
  124. void DestroyTexture(GLuint service_id) override {
  125. DVLOG(2) << __func__ << "(" << service_id << ")";
  126. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  127. DCHECK(stub_->decoder_context()->GetGLContext()->IsCurrent(nullptr));
  128. DCHECK(textures_.count(service_id));
  129. textures_.erase(service_id);
  130. }
  131. void SetCleared(GLuint service_id) override {
  132. DVLOG(2) << __func__ << "(" << service_id << ")";
  133. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  134. DCHECK(textures_.count(service_id));
  135. textures_[service_id]->SetCleared();
  136. }
  137. bool BindImage(GLuint service_id,
  138. gl::GLImage* image,
  139. bool client_managed) override {
  140. DVLOG(2) << __func__ << "(" << service_id << ")";
  141. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  142. DCHECK(textures_.count(service_id));
  143. textures_[service_id]->BindImage(image, client_managed);
  144. return true;
  145. }
  146. gpu::Mailbox CreateMailbox(GLuint service_id) override {
  147. DVLOG(2) << __func__ << "(" << service_id << ")";
  148. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  149. if (!decoder_helper_)
  150. return gpu::Mailbox();
  151. DCHECK(textures_.count(service_id));
  152. return decoder_helper_->CreateMailbox(textures_[service_id].get());
  153. }
  154. void ProduceTexture(const gpu::Mailbox& mailbox, GLuint service_id) override {
  155. DVLOG(2) << __func__ << "(" << mailbox.ToDebugString() << ", " << service_id
  156. << ")";
  157. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  158. if (!decoder_helper_)
  159. return;
  160. DCHECK(textures_.count(service_id));
  161. return decoder_helper_->ProduceTexture(mailbox,
  162. textures_[service_id].get());
  163. }
  164. void WaitForSyncToken(gpu::SyncToken sync_token,
  165. base::OnceClosure done_cb) override {
  166. DVLOG(2) << __func__;
  167. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  168. if (!stub_)
  169. return;
  170. // TODO(sandersd): Do we need to keep a ref to |this| while there are
  171. // pending waits? If we destruct while they are pending, they will never
  172. // run.
  173. stub_->channel()->scheduler()->ScheduleTask(
  174. gpu::Scheduler::Task(wait_sequence_id_, std::move(done_cb),
  175. std::vector<gpu::SyncToken>({sync_token})));
  176. }
  177. void SetWillDestroyStubCB(WillDestroyStubCB will_destroy_stub_cb) override {
  178. DCHECK(!will_destroy_stub_cb_);
  179. will_destroy_stub_cb_ = std::move(will_destroy_stub_cb);
  180. }
  181. bool IsPassthrough() const override {
  182. if (!stub_)
  183. return false;
  184. return stub_->decoder_context()
  185. ->GetFeatureInfo()
  186. ->is_passthrough_cmd_decoder();
  187. }
  188. bool SupportsTextureRectangle() const override {
  189. if (!stub_)
  190. return false;
  191. return stub_->decoder_context()
  192. ->GetFeatureInfo()
  193. ->feature_flags()
  194. .arb_texture_rectangle;
  195. }
  196. private:
  197. // Helper class to forward memory tracking calls to shared image stub.
  198. // Necessary because the underlying stub and channel can get destroyed before
  199. // the CommandBufferHelper and its clients.
  200. class MemoryTrackerImpl : public gpu::MemoryTracker {
  201. public:
  202. explicit MemoryTrackerImpl(CommandBufferHelperImpl* helper)
  203. : helper_(helper) {
  204. if (auto* stub = helper_->shared_image_stub()) {
  205. // We assume these don't change after initialization.
  206. client_id_ = stub->ClientId();
  207. client_tracing_id_ = stub->ClientTracingId();
  208. context_group_tracing_id_ = stub->ContextGroupTracingId();
  209. }
  210. }
  211. ~MemoryTrackerImpl() override = default;
  212. MemoryTrackerImpl(const MemoryTrackerImpl&) = delete;
  213. MemoryTrackerImpl& operator=(const MemoryTrackerImpl&) = delete;
  214. void TrackMemoryAllocatedChange(int64_t delta) override {
  215. if (auto* stub = helper_->shared_image_stub())
  216. stub->TrackMemoryAllocatedChange(delta);
  217. }
  218. uint64_t GetSize() const override {
  219. if (auto* stub = helper_->shared_image_stub())
  220. return stub->GetSize();
  221. return 0;
  222. }
  223. int ClientId() const override { return client_id_; }
  224. uint64_t ClientTracingId() const override { return client_tracing_id_; }
  225. uint64_t ContextGroupTracingId() const override {
  226. return context_group_tracing_id_;
  227. }
  228. private:
  229. const raw_ptr<CommandBufferHelperImpl> helper_;
  230. int client_id_ = 0;
  231. uint64_t client_tracing_id_ = 0;
  232. uint64_t context_group_tracing_id_ = 0;
  233. };
  234. ~CommandBufferHelperImpl() override {
  235. DVLOG(1) << __func__;
  236. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  237. if (stub_)
  238. DestroyStub();
  239. }
  240. void OnWillDestroyStub(bool have_context) override {
  241. DVLOG(1) << __func__;
  242. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  243. // In case |will_destroy_stub_cb_| drops the last reference to |this|, make
  244. // sure that we're around a bit longer.
  245. scoped_refptr<CommandBufferHelper> thiz(this);
  246. if (will_destroy_stub_cb_)
  247. std::move(will_destroy_stub_cb_).Run(have_context);
  248. DestroyStub();
  249. }
  250. void DestroyStub() {
  251. DVLOG(3) << __func__;
  252. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  253. decoder_helper_ = nullptr;
  254. // If the last reference to |this| is in a |done_cb|, destroying the wait
  255. // sequence can delete |this|. Clearing |stub_| first prevents DestroyStub()
  256. // being called twice.
  257. gpu::CommandBufferStub* stub = stub_;
  258. stub_ = nullptr;
  259. stub->RemoveDestructionObserver(this);
  260. stub->channel()->scheduler()->DestroySequence(wait_sequence_id_);
  261. }
  262. raw_ptr<gpu::CommandBufferStub> stub_;
  263. // Wait tasks are scheduled on our own sequence so that we can't inadvertently
  264. // block the command buffer.
  265. gpu::SequenceId wait_sequence_id_;
  266. // TODO(sandersd): Merge GLES2DecoderHelper implementation into this class.
  267. std::unique_ptr<GLES2DecoderHelper> decoder_helper_;
  268. std::map<GLuint, std::unique_ptr<gpu::gles2::AbstractTexture>> textures_;
  269. WillDestroyStubCB will_destroy_stub_cb_;
  270. MemoryTrackerImpl memory_tracker_;
  271. gpu::MemoryTypeTracker memory_type_tracker_;
  272. THREAD_CHECKER(thread_checker_);
  273. };
  274. } // namespace
  275. CommandBufferHelper::CommandBufferHelper(
  276. scoped_refptr<base::SequencedTaskRunner> task_runner)
  277. : base::RefCountedDeleteOnSequence<CommandBufferHelper>(
  278. std::move(task_runner)) {}
  279. // static
  280. scoped_refptr<CommandBufferHelper> CommandBufferHelper::Create(
  281. gpu::CommandBufferStub* stub) {
  282. return base::MakeRefCounted<CommandBufferHelperImpl>(stub);
  283. }
  284. } // namespace media