blob: 58c12117d51ea4fd8486427593fb7e233a77fc3e [file] [log] [blame]
// Copyright 2014 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 "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
#include "base/bind.h"
#include "base/debug/trace_event.h"
#include "base/lazy_instance.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread_restrictions.h"
#include "content/common/gpu/client/gpu_memory_buffer_impl.h"
#include "content/public/browser/browser_thread.h"
namespace content {
namespace {
void GpuMemoryBufferAllocatedForChildProcess(
const BrowserGpuMemoryBufferManager::AllocationCallback& callback,
const gfx::GpuMemoryBufferHandle& handle) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
callback.Run(handle);
}
BrowserGpuMemoryBufferManager* g_gpu_memory_buffer_manager = nullptr;
} // namespace
struct BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferRequest {
AllocateGpuMemoryBufferRequest(const gfx::Size& size,
gfx::GpuMemoryBuffer::Format format,
gfx::GpuMemoryBuffer::Usage usage,
int client_id)
: event(true, false),
size(size),
format(format),
usage(usage),
client_id(client_id) {}
~AllocateGpuMemoryBufferRequest() {}
base::WaitableEvent event;
gfx::Size size;
gfx::GpuMemoryBuffer::Format format;
gfx::GpuMemoryBuffer::Usage usage;
int client_id;
scoped_ptr<gfx::GpuMemoryBuffer> result;
};
BrowserGpuMemoryBufferManager::BrowserGpuMemoryBufferManager(int gpu_client_id)
: gpu_client_id_(gpu_client_id) {
DCHECK(!g_gpu_memory_buffer_manager);
g_gpu_memory_buffer_manager = this;
}
BrowserGpuMemoryBufferManager::~BrowserGpuMemoryBufferManager() {
g_gpu_memory_buffer_manager = nullptr;
}
// static
BrowserGpuMemoryBufferManager* BrowserGpuMemoryBufferManager::current() {
return g_gpu_memory_buffer_manager;
}
scoped_ptr<gfx::GpuMemoryBuffer>
BrowserGpuMemoryBufferManager::AllocateGpuMemoryBuffer(
const gfx::Size& size,
gfx::GpuMemoryBuffer::Format format,
gfx::GpuMemoryBuffer::Usage usage) {
DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
AllocateGpuMemoryBufferRequest request(size, format, usage, gpu_client_id_);
BrowserThread::PostTask(
BrowserThread::IO,
FROM_HERE,
base::Bind(&BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferOnIO,
base::Unretained(&request)));
// We're blocking the UI thread, which is generally undesirable.
TRACE_EVENT0("browser",
"BrowserGpuMemoryBufferManager::AllocateGpuMemoryBuffer");
base::ThreadRestrictions::ScopedAllowWait allow_wait;
request.event.Wait();
return request.result.Pass();
}
void BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferForChildProcess(
const gfx::Size& size,
gfx::GpuMemoryBuffer::Format format,
gfx::GpuMemoryBuffer::Usage usage,
base::ProcessHandle child_process_handle,
int child_client_id,
const AllocationCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
GpuMemoryBufferImpl::AllocateForChildProcess(
size,
format,
usage,
child_process_handle,
child_client_id,
base::Bind(&GpuMemoryBufferAllocatedForChildProcess, callback));
}
gfx::GpuMemoryBuffer*
BrowserGpuMemoryBufferManager::GpuMemoryBufferFromClientBuffer(
ClientBuffer buffer) {
return GpuMemoryBufferImpl::FromClientBuffer(buffer);
}
void BrowserGpuMemoryBufferManager::ChildProcessDeletedGpuMemoryBuffer(
gfx::GpuMemoryBufferType type,
const gfx::GpuMemoryBufferId& id,
base::ProcessHandle child_process_handle) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
GpuMemoryBufferImpl::DeletedByChildProcess(type, id, child_process_handle);
}
void BrowserGpuMemoryBufferManager::ProcessRemoved(
base::ProcessHandle process_handle) {
// TODO(reveman): Handle child process removal correctly.
}
// static
void BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferOnIO(
AllocateGpuMemoryBufferRequest* request) {
GpuMemoryBufferImpl::Create(
request->size,
request->format,
request->usage,
request->client_id,
base::Bind(&BrowserGpuMemoryBufferManager::GpuMemoryBufferCreatedOnIO,
base::Unretained(request)));
}
// static
void BrowserGpuMemoryBufferManager::GpuMemoryBufferCreatedOnIO(
AllocateGpuMemoryBufferRequest* request,
scoped_ptr<GpuMemoryBufferImpl> buffer) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
request->result = buffer.PassAs<gfx::GpuMemoryBuffer>();
request->event.Signal();
}
} // namespace content