| Index: services/ui/public/cpp/mojo_gpu_memory_buffer_manager.cc
 | 
| diff --git a/services/ui/public/cpp/mojo_gpu_memory_buffer_manager.cc b/services/ui/public/cpp/mojo_gpu_memory_buffer_manager.cc
 | 
| index 81b5620d7bc213fb1886251dda83f112af64c5e4..1c4d027e3feceb6aa259742e29fe005a75fdfdb1 100644
 | 
| --- a/services/ui/public/cpp/mojo_gpu_memory_buffer_manager.cc
 | 
| +++ b/services/ui/public/cpp/mojo_gpu_memory_buffer_manager.cc
 | 
| @@ -8,21 +8,80 @@
 | 
|  #include "base/logging.h"
 | 
|  #include "base/memory/ptr_util.h"
 | 
|  #include "base/memory/shared_memory.h"
 | 
| +#include "base/synchronization/waitable_event.h"
 | 
|  #include "gpu/ipc/client/gpu_memory_buffer_impl.h"
 | 
|  #include "mojo/public/cpp/system/buffer.h"
 | 
|  #include "mojo/public/cpp/system/platform_handle.h"
 | 
| +#include "services/service_manager/public/cpp/connector.h"
 | 
|  #include "ui/gfx/buffer_format_util.h"
 | 
|  
 | 
|  namespace ui {
 | 
|  
 | 
| -MojoGpuMemoryBufferManager::MojoGpuMemoryBufferManager()
 | 
| -    : weak_ptr_factory_(this) {}
 | 
| +namespace {
 | 
|  
 | 
| -MojoGpuMemoryBufferManager::~MojoGpuMemoryBufferManager() {}
 | 
| +void OnGpuMemoryBufferAllocated(gfx::GpuMemoryBufferHandle* ret_handle,
 | 
| +                                base::WaitableEvent* wait,
 | 
| +                                const gfx::GpuMemoryBufferHandle& handle) {
 | 
| +  *ret_handle = handle;
 | 
| +  wait->Signal();
 | 
| +}
 | 
| +
 | 
| +}  // namespace
 | 
| +
 | 
| +MojoGpuMemoryBufferManager::MojoGpuMemoryBufferManager(
 | 
| +    service_manager::Connector* connector)
 | 
| +    : thread_("GpuMemoryThread"),
 | 
| +      connector_(connector->Clone()),
 | 
| +      weak_ptr_factory_(this) {
 | 
| +  CHECK(thread_.Start());
 | 
| +  // The thread is owned by this object. Which means the test will not run if
 | 
| +  // the object has been destroyed. So Unretained() is safe.
 | 
| +  thread_.task_runner()->PostTask(
 | 
| +      FROM_HERE, base::Bind(&MojoGpuMemoryBufferManager::InitThread,
 | 
| +                            base::Unretained(this)));
 | 
| +}
 | 
| +
 | 
| +MojoGpuMemoryBufferManager::~MojoGpuMemoryBufferManager() {
 | 
| +  thread_.task_runner()->PostTask(
 | 
| +      FROM_HERE, base::Bind(&MojoGpuMemoryBufferManager::TearDownThread,
 | 
| +                            base::Unretained(this)));
 | 
| +  thread_.Stop();
 | 
| +}
 | 
| +
 | 
| +void MojoGpuMemoryBufferManager::InitThread() {
 | 
| +  connector_->ConnectToInterface("service:ui", &gpu_service_);
 | 
| +}
 | 
| +
 | 
| +void MojoGpuMemoryBufferManager::TearDownThread() {
 | 
| +  gpu_service_.reset();
 | 
| +}
 | 
| +
 | 
| +void MojoGpuMemoryBufferManager::AllocateGpuMemoryBufferOnThread(
 | 
| +    const gfx::Size& size,
 | 
| +    gfx::BufferFormat format,
 | 
| +    gfx::BufferUsage usage,
 | 
| +    gfx::GpuMemoryBufferHandle* handle,
 | 
| +    base::WaitableEvent* wait) {
 | 
| +  DCHECK(thread_.task_runner()->BelongsToCurrentThread());
 | 
| +  // |handle| and |wait| are both on the stack, and will be alive until |wait|
 | 
| +  // is signaled. So it is safe for OnGpuMemoryBufferAllocated() to operate on
 | 
| +  // these.
 | 
| +  gpu_service_->CreateGpuMemoryBuffer(
 | 
| +      gfx::GpuMemoryBufferId(++counter_), size, format, usage,
 | 
| +      base::Bind(&OnGpuMemoryBufferAllocated, handle, wait));
 | 
| +}
 | 
|  
 | 
|  void MojoGpuMemoryBufferManager::DeletedGpuMemoryBuffer(
 | 
|      gfx::GpuMemoryBufferId id,
 | 
|      const gpu::SyncToken& sync_token) {
 | 
| +  if (!thread_.task_runner()->BelongsToCurrentThread()) {
 | 
| +    thread_.task_runner()->PostTask(
 | 
| +        FROM_HERE,
 | 
| +        base::Bind(&MojoGpuMemoryBufferManager::DeletedGpuMemoryBuffer,
 | 
| +                   base::Unretained(this), id, sync_token));
 | 
| +    return;
 | 
| +  }
 | 
| +  gpu_service_->DestroyGpuMemoryBuffer(id, sync_token);
 | 
|  }
 | 
|  
 | 
|  std::unique_ptr<gfx::GpuMemoryBuffer>
 | 
| @@ -31,41 +90,30 @@ MojoGpuMemoryBufferManager::AllocateGpuMemoryBuffer(
 | 
|      gfx::BufferFormat format,
 | 
|      gfx::BufferUsage usage,
 | 
|      gpu::SurfaceHandle surface_handle) {
 | 
| -  // TODO(sad): Get the memory buffer handle from GpuService.
 | 
| -  size_t bytes = gfx::BufferSizeForBufferFormat(size, format);
 | 
| -
 | 
| -  mojo::ScopedSharedBufferHandle handle =
 | 
| -      mojo::SharedBufferHandle::Create(bytes);
 | 
| -  if (!handle.is_valid())
 | 
| -    return nullptr;
 | 
| -
 | 
| -  base::SharedMemoryHandle shm_handle;
 | 
| -  size_t shared_memory_size;
 | 
| -  bool readonly;
 | 
| -  MojoResult result = mojo::UnwrapSharedMemoryHandle(
 | 
| -      std::move(handle), &shm_handle, &shared_memory_size, &readonly);
 | 
| -  if (result != MOJO_RESULT_OK)
 | 
| -    return nullptr;
 | 
| -  DCHECK_EQ(shared_memory_size, bytes);
 | 
| -
 | 
| -  const int stride = base::checked_cast<int>(
 | 
| -      gfx::RowSizeForBufferFormat(size.width(), format, 0));
 | 
| -
 | 
| +  // Note: this can be called from multiple threads at the same time. Some of
 | 
| +  // those threads may not have a TaskRunner set.
 | 
| +  DCHECK_EQ(gpu::kNullSurfaceHandle, surface_handle);
 | 
| +  CHECK(!thread_.task_runner()->BelongsToCurrentThread());
 | 
|    gfx::GpuMemoryBufferHandle gmb_handle;
 | 
| -  gmb_handle.type = gfx::SHARED_MEMORY_BUFFER;
 | 
| -  gmb_handle.id = gfx::GpuMemoryBufferId(++counter_);
 | 
| -  gmb_handle.handle = shm_handle;
 | 
| -  gmb_handle.offset = 0;
 | 
| -  gmb_handle.stride = stride;
 | 
| -
 | 
| +  base::WaitableEvent wait(base::WaitableEvent::ResetPolicy::AUTOMATIC,
 | 
| +                           base::WaitableEvent::InitialState::NOT_SIGNALED);
 | 
| +  thread_.task_runner()->PostTask(
 | 
| +      FROM_HERE,
 | 
| +      base::Bind(&MojoGpuMemoryBufferManager::AllocateGpuMemoryBufferOnThread,
 | 
| +                 base::Unretained(this), size, format, usage, &gmb_handle,
 | 
| +                 &wait));
 | 
| +  wait.Wait();
 | 
| +  if (gmb_handle.is_null())
 | 
| +    return nullptr;
 | 
|    std::unique_ptr<gpu::GpuMemoryBufferImpl> buffer(
 | 
|        gpu::GpuMemoryBufferImpl::CreateFromHandle(
 | 
|            gmb_handle, size, format, usage,
 | 
|            base::Bind(&MojoGpuMemoryBufferManager::DeletedGpuMemoryBuffer,
 | 
|                       weak_ptr_factory_.GetWeakPtr(), gmb_handle.id)));
 | 
| -  if (!buffer)
 | 
| +  if (!buffer) {
 | 
| +    DeletedGpuMemoryBuffer(gmb_handle.id, gpu::SyncToken());
 | 
|      return nullptr;
 | 
| -
 | 
| +  }
 | 
|    return std::move(buffer);
 | 
|  }
 | 
|  
 | 
| 
 |