Chromium Code Reviews| Index: media/gpu/command_buffer_helper.cc |
| diff --git a/media/gpu/command_buffer_helper.cc b/media/gpu/command_buffer_helper.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..9cc5ba7d3aa3a2af11ebdce964463b8c97bb071c |
| --- /dev/null |
| +++ b/media/gpu/command_buffer_helper.cc |
| @@ -0,0 +1,176 @@ |
| +// Copyright 2017 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "media/gpu/command_buffer_helper.h" |
| + |
| +#include "base/macros.h" |
| +#include "base/memory/ptr_util.h" |
| +#include "base/threading/thread_checker.h" |
| +#include "gpu/command_buffer/common/mailbox.h" |
| +#include "gpu/command_buffer/common/sync_token.h" |
| +#include "gpu/command_buffer/service/gles2_cmd_decoder.h" |
| +#include "gpu/command_buffer/service/mailbox_manager.h" |
| +#include "gpu/command_buffer/service/texture_manager.h" |
| +#include "gpu/ipc/service/gpu_command_buffer_stub.h" |
| + |
| +namespace media { |
| + |
| +class CommandBufferHelperImpl |
| + : public CommandBufferHelper, |
| + private gpu::GpuCommandBufferStub::DestructionObserver { |
| + public: |
| + explicit CommandBufferHelperImpl(gpu::GpuCommandBufferStub* stub) |
|
sunnyps
2017/06/23 00:57:59
nit: Make the helper take a decoder instead of the
sandersd (OOO until July 31)
2017/06/26 21:00:27
I'm not sure about this, because it means that Cre
|
| + : stub_(stub) { |
| + stub_->AddDestructionObserver(this); |
| + } |
| + |
| + ~CommandBufferHelperImpl() override { |
| + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| + if (stub_) |
| + stub_->RemoveDestructionObserver(this); |
| + } |
| + |
| + bool MakeContextCurrent() override { |
| + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| + if (!stub_) |
| + return false; |
| + gpu::gles2::GLES2Decoder* decoder = stub_->decoder(); |
| + if (!decoder) |
| + return false; |
| + return decoder->MakeCurrent(); |
| + } |
| + |
| + scoped_refptr<gpu::gles2::TextureRef> CreateTexture(GLenum target, |
| + GLenum internal_format, |
| + GLsizei width, |
| + GLsizei height, |
| + GLenum format, |
| + GLenum type) override { |
| + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| + if (!stub_) |
| + return nullptr; |
| + gpu::gles2::GLES2Decoder* decoder = stub_->decoder(); |
| + if (!decoder) |
| + return nullptr; |
| + gpu::gles2::ContextGroup* group = decoder->GetContextGroup(); |
| + if (!group) |
| + return nullptr; |
| + gpu::gles2::TextureManager* texture_manager = group->texture_manager(); |
| + if (!texture_manager) |
| + return nullptr; |
| + |
| + // We can't use texture_manager->CreateTexture(), since it requires a unique |
| + // |client_id|. Instead we create the texture directly, and create our own |
| + // TextureRef for it. |
| + GLuint texture_id; |
| + glGenTextures(1, &texture_id); |
| + glBindTexture(target, texture_id); |
| + |
| + scoped_refptr<gpu::gles2::TextureRef> texture_ref = |
| + gpu::gles2::TextureRef::Create(texture_manager, 0, texture_id); |
| + texture_manager->SetTarget(texture_ref.get(), target); |
| + texture_manager->SetLevelInfo(texture_ref.get(), // ref |
| + target, // target |
| + 0, // level |
| + internal_format, // internal_format |
| + width, // width |
| + height, // height |
| + 1, // depth |
| + 0, // border |
| + format, // format |
| + type, // type |
| + gfx::Rect()); // cleared_rect |
| + |
| + texture_manager->SetParameteri(__func__, decoder->GetErrorState(), |
| + texture_ref.get(), GL_TEXTURE_MAG_FILTER, |
| + GL_LINEAR); |
| + texture_manager->SetParameteri(__func__, decoder->GetErrorState(), |
| + texture_ref.get(), GL_TEXTURE_MIN_FILTER, |
| + GL_LINEAR); |
| + |
| + texture_manager->SetParameteri(__func__, decoder->GetErrorState(), |
| + texture_ref.get(), GL_TEXTURE_WRAP_S, |
| + GL_CLAMP_TO_EDGE); |
| + texture_manager->SetParameteri(__func__, decoder->GetErrorState(), |
| + texture_ref.get(), GL_TEXTURE_WRAP_T, |
| + GL_CLAMP_TO_EDGE); |
| + |
| + texture_manager->SetParameteri(__func__, decoder->GetErrorState(), |
| + texture_ref.get(), GL_TEXTURE_BASE_LEVEL, 0); |
| + texture_manager->SetParameteri(__func__, decoder->GetErrorState(), |
| + texture_ref.get(), GL_TEXTURE_MAX_LEVEL, 0); |
| + |
| + // TODO(sandersd): Do we always want to allocate for GL_TEXTURE_2D? |
| + if (target == GL_TEXTURE_2D) { |
| + glTexImage2D(target, // target |
| + 0, // level |
| + internal_format, // internal_format |
| + width, // width |
| + height, // height |
| + 0, // border |
| + format, // format |
| + type, // type |
| + nullptr); // data |
| + } |
| + |
| + decoder->RestoreActiveTextureUnitBinding(target); |
| + return texture_ref; |
| + } |
| + |
| + base::Optional<gpu::SyncToken> CreateSyncToken() override { |
| + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| + if (!stub_) |
| + return base::nullopt; |
| + |
| + // TODO(sandersd): Handle namespaces other than GPU_IO, for example the |
| + // IN_PROCESS kind used in GPU tests. For now, VdaVideoDecoder clients |
| + // should only use GPU_IO command buffers. |
| + gpu::SyncToken sync_token = |
| + gpu::SyncToken(gpu::CommandBufferNamespace::GPU_IO, stub_->stream_id(), |
| + stub_->command_buffer_id(), 0); |
| + sync_token.SetVerifyFlush(); |
| + return sync_token; |
| + } |
| + |
| + base::Optional<gpu::Mailbox> CreateMailbox( |
| + gpu::gles2::TextureRef* texture_ref) override { |
| + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| + if (!stub_) |
| + return base::nullopt; |
| + gpu::gles2::GLES2Decoder* decoder = stub_->decoder(); |
| + if (!decoder) |
| + return base::nullopt; |
| + gpu::gles2::ContextGroup* group = decoder->GetContextGroup(); |
| + if (!group) |
| + return base::nullopt; |
| + gpu::gles2::MailboxManager* mailbox_manager = group->mailbox_manager(); |
| + if (!mailbox_manager) |
| + return base::nullopt; |
| + |
| + gpu::Mailbox mailbox = gpu::Mailbox::Generate(); |
| + mailbox_manager->ProduceTexture(mailbox, texture_ref->texture()); |
| + return mailbox; |
| + } |
| + |
| + private: |
| + void OnWillDestroyStub() override { |
| + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| + stub_ = nullptr; |
| + } |
| + |
| + gpu::GpuCommandBufferStub* stub_; |
| + THREAD_CHECKER(thread_checker_); |
| + |
| + DISALLOW_COPY_AND_ASSIGN(CommandBufferHelperImpl); |
| +}; |
| + |
| +// static |
| +std::unique_ptr<CommandBufferHelper> CommandBufferHelper::Create( |
| + gpu::GpuCommandBufferStub* stub) { |
| + if (!stub) |
| + return nullptr; |
| + return base::MakeUnique<CommandBufferHelperImpl>(stub); |
| +} |
| + |
| +} // namespace media |