Commit a206fb49 authored by penghuang's avatar penghuang Committed by Commit bot

When use the Pepper MapTexSubImage2DCHROMIUM() and the Compositor API...

When use the Pepper MapTexSubImage2DCHROMIUM() and the Compositor API together, it may cause memory leak, and then run out of memory. The problem is because the Compositor API uses sync point to sync texture producer and the Chrome compositor, it does not need any IPC, so the PpapiCommandBufferProxy::last_state_[1] will not get updated, so the client does not known when the GPU process finishes accessing the memory, and then the memory can not be reused forever. This change add a shared state in PpapiCommandBufferProxy. It allows PpapiCommandBufferProxy updating state from a shared memory without an IPC. It fix this issue.

BUG=411004

Review URL: https://codereview.chromium.org/547733002

Cr-Commit-Position: refs/heads/master@{#294012}
parent 1fed1b5f
......@@ -141,6 +141,10 @@ class CommandBufferProxyImpl
GpuChannelHost* channel() const { return channel_; }
base::SharedMemoryHandle GetSharedStateHandle() const {
return shared_state_shm_->handle();
}
private:
typedef std::map<int32, scoped_refptr<gpu::Buffer> > TransferBufferMap;
typedef base::hash_map<uint32, base::Closure> SignalTaskMap;
......
......@@ -81,9 +81,11 @@ PP_Resource PPB_Graphics3D_Impl::Create(PP_Instance instance,
}
// static
PP_Resource PPB_Graphics3D_Impl::CreateRaw(PP_Instance instance,
PP_Resource share_context,
const int32_t* attrib_list) {
PP_Resource PPB_Graphics3D_Impl::CreateRaw(
PP_Instance instance,
PP_Resource share_context,
const int32_t* attrib_list,
base::SharedMemoryHandle* shared_state_handle) {
PPB_Graphics3D_API* share_api = NULL;
if (share_context) {
EnterResourceNoLock<PPB_Graphics3D_API> enter(share_context, true);
......@@ -93,7 +95,7 @@ PP_Resource PPB_Graphics3D_Impl::CreateRaw(PP_Instance instance,
}
scoped_refptr<PPB_Graphics3D_Impl> graphics_3d(
new PPB_Graphics3D_Impl(instance));
if (!graphics_3d->InitRaw(share_api, attrib_list))
if (!graphics_3d->InitRaw(share_api, attrib_list, shared_state_handle))
return 0;
return graphics_3d->GetReference();
}
......@@ -207,7 +209,7 @@ int32 PPB_Graphics3D_Impl::DoSwapBuffers() {
bool PPB_Graphics3D_Impl::Init(PPB_Graphics3D_API* share_context,
const int32_t* attrib_list) {
if (!InitRaw(share_context, attrib_list))
if (!InitRaw(share_context, attrib_list, NULL))
return false;
gpu::gles2::GLES2Implementation* share_gles2 = NULL;
......@@ -219,8 +221,10 @@ bool PPB_Graphics3D_Impl::Init(PPB_Graphics3D_API* share_context,
return CreateGLES2Impl(kCommandBufferSize, kTransferBufferSize, share_gles2);
}
bool PPB_Graphics3D_Impl::InitRaw(PPB_Graphics3D_API* share_context,
const int32_t* attrib_list) {
bool PPB_Graphics3D_Impl::InitRaw(
PPB_Graphics3D_API* share_context,
const int32_t* attrib_list,
base::SharedMemoryHandle* shared_state_handle) {
PepperPluginInstanceImpl* plugin_instance =
HostGlobals::Get()->GetInstance(pp_instance());
if (!plugin_instance)
......@@ -289,6 +293,8 @@ bool PPB_Graphics3D_Impl::InitRaw(PPB_Graphics3D_API* share_context,
return false;
if (!command_buffer_->Initialize())
return false;
if (shared_state_handle)
*shared_state_handle = command_buffer_->GetSharedStateHandle();
mailbox_ = gpu::Mailbox::Generate();
if (!command_buffer_->ProduceFrontBuffer(mailbox_))
return false;
......
......@@ -5,6 +5,7 @@
#ifndef CONTENT_RENDERER_PEPPER_PPB_GRAPHICS_3D_IMPL_H_
#define CONTENT_RENDERER_PEPPER_PPB_GRAPHICS_3D_IMPL_H_
#include "base/memory/shared_memory.h"
#include "base/memory/weak_ptr.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "ppapi/shared_impl/ppb_graphics_3d_shared.h"
......@@ -19,9 +20,11 @@ class PPB_Graphics3D_Impl : public ppapi::PPB_Graphics3D_Shared {
static PP_Resource Create(PP_Instance instance,
PP_Resource share_context,
const int32_t* attrib_list);
static PP_Resource CreateRaw(PP_Instance instance,
PP_Resource share_context,
const int32_t* attrib_list);
static PP_Resource CreateRaw(
PP_Instance instance,
PP_Resource share_context,
const int32_t* attrib_list,
base::SharedMemoryHandle* shared_state_handle);
// PPB_Graphics3D_API trusted implementation.
virtual PP_Bool SetGetBuffer(int32_t transfer_buffer_id) OVERRIDE;
......@@ -70,7 +73,9 @@ class PPB_Graphics3D_Impl : public ppapi::PPB_Graphics3D_Shared {
explicit PPB_Graphics3D_Impl(PP_Instance instance);
bool Init(PPB_Graphics3D_API* share_context, const int32_t* attrib_list);
bool InitRaw(PPB_Graphics3D_API* share_context, const int32_t* attrib_list);
bool InitRaw(PPB_Graphics3D_API* share_context,
const int32_t* attrib_list,
base::SharedMemoryHandle* shared_state_handle);
// Notifications received from the GPU process.
void OnSwapBuffers();
......
......@@ -106,8 +106,10 @@ PP_Resource ResourceCreationImpl::CreateGraphics3D(PP_Instance instance,
PP_Resource ResourceCreationImpl::CreateGraphics3DRaw(
PP_Instance instance,
PP_Resource share_context,
const int32_t* attrib_list) {
return PPB_Graphics3D_Impl::CreateRaw(instance, share_context, attrib_list);
const int32_t* attrib_list,
base::SharedMemoryHandle* shared_state) {
return PPB_Graphics3D_Impl::CreateRaw(instance, share_context, attrib_list,
shared_state);
}
PP_Resource ResourceCreationImpl::CreateHostResolver(PP_Instance instance) {
......
......@@ -51,9 +51,11 @@ class ResourceCreationImpl : public ppapi::thunk::ResourceCreationAPI {
virtual PP_Resource CreateGraphics3D(PP_Instance instance,
PP_Resource share_context,
const int32_t* attrib_list) OVERRIDE;
virtual PP_Resource CreateGraphics3DRaw(PP_Instance instance,
PP_Resource share_context,
const int32_t* attrib_list) OVERRIDE;
virtual PP_Resource CreateGraphics3DRaw(
PP_Instance instance,
PP_Resource share_context,
const int32_t* attrib_list,
base::SharedMemoryHandle* shared_state) OVERRIDE;
virtual PP_Resource CreateHostResolver(PP_Instance instance) OVERRIDE;
virtual PP_Resource CreateHostResolverPrivate(PP_Instance instance) OVERRIDE;
virtual PP_Resource CreateImageData(PP_Instance instance,
......
......@@ -182,7 +182,8 @@ PP_Resource ResourceCreationImpl::CreateGraphics3D(
PP_Resource ResourceCreationImpl::CreateGraphics3DRaw(
PP_Instance instance,
PP_Resource share_context,
const int32_t* attrib_list) {
const int32_t* attrib_list,
base::SharedMemoryHandle* shared_state) {
NOTIMPLEMENTED();
return 0;
}
......
......@@ -101,7 +101,8 @@ class ResourceCreationImpl : public ppapi::thunk::ResourceCreationAPI {
virtual PP_Resource CreateGraphics3DRaw(
PP_Instance instance,
PP_Resource share_context,
const int32_t* attrib_list) OVERRIDE;
const int32_t* attrib_list,
base::SharedMemoryHandle* shared_state) OVERRIDE;
virtual PP_Resource CreateHostResolver(PP_Instance instance) OVERRIDE;
virtual PP_Resource CreateHostResolverPrivate(PP_Instance instance) OVERRIDE;
virtual PP_Resource CreateImageData(PP_Instance instance,
......
......@@ -318,6 +318,7 @@ bool NaClMessageScanner::ScanMessage(
CASE_FOR_MESSAGE(PpapiMsg_PPBAudio_NotifyAudioStreamCreated)
CASE_FOR_MESSAGE(PpapiMsg_PPPMessaging_HandleMessage)
CASE_FOR_MESSAGE(PpapiPluginMsg_ResourceReply)
CASE_FOR_REPLY(PpapiHostMsg_PPBGraphics3D_Create)
CASE_FOR_REPLY(PpapiHostMsg_PPBGraphics3D_CreateTransferBuffer)
CASE_FOR_REPLY(PpapiHostMsg_PPBImageData_CreateSimple)
CASE_FOR_REPLY(PpapiHostMsg_ResourceSyncCall)
......
......@@ -15,9 +15,13 @@ namespace proxy {
PpapiCommandBufferProxy::PpapiCommandBufferProxy(
const ppapi::HostResource& resource,
ProxyChannel* channel)
ProxyChannel* channel,
const SerializedHandle& shared_state)
: resource_(resource),
channel_(channel) {
shared_state_shm_.reset(
new base::SharedMemory(shared_state.shmem(), false));
shared_state_shm_->Map(shared_state.size());
}
PpapiCommandBufferProxy::~PpapiCommandBufferProxy() {
......@@ -36,6 +40,7 @@ gpu::CommandBuffer::State PpapiCommandBufferProxy::GetLastState() {
int32 PpapiCommandBufferProxy::GetLastToken() {
ppapi::ProxyLock::AssertAcquiredDebugOnly();
TryUpdateState();
return last_state_.token;
}
......@@ -54,35 +59,41 @@ void PpapiCommandBufferProxy::Flush(int32 put_offset) {
}
void PpapiCommandBufferProxy::WaitForTokenInRange(int32 start, int32 end) {
if (last_state_.error != gpu::error::kNoError)
return;
bool success = false;
gpu::CommandBuffer::State state;
if (Send(new PpapiHostMsg_PPBGraphics3D_WaitForTokenInRange(
ppapi::API_ID_PPB_GRAPHICS_3D,
resource_,
start,
end,
&state,
&success)))
UpdateState(state, success);
TryUpdateState();
if (!InRange(start, end, last_state_.token) &&
last_state_.error == gpu::error::kNoError) {
bool success = false;
gpu::CommandBuffer::State state;
if (Send(new PpapiHostMsg_PPBGraphics3D_WaitForTokenInRange(
ppapi::API_ID_PPB_GRAPHICS_3D,
resource_,
start,
end,
&state,
&success)))
UpdateState(state, success);
}
DCHECK(InRange(start, end, last_state_.token) ||
last_state_.error != gpu::error::kNoError);
}
void PpapiCommandBufferProxy::WaitForGetOffsetInRange(int32 start, int32 end) {
if (last_state_.error != gpu::error::kNoError)
return;
bool success = false;
gpu::CommandBuffer::State state;
if (Send(new PpapiHostMsg_PPBGraphics3D_WaitForGetOffsetInRange(
ppapi::API_ID_PPB_GRAPHICS_3D,
resource_,
start,
end,
&state,
&success)))
UpdateState(state, success);
TryUpdateState();
if (!InRange(start, end, last_state_.get_offset) &&
last_state_.error == gpu::error::kNoError) {
bool success = false;
gpu::CommandBuffer::State state;
if (Send(new PpapiHostMsg_PPBGraphics3D_WaitForGetOffsetInRange(
ppapi::API_ID_PPB_GRAPHICS_3D,
resource_,
start,
end,
&state,
&success)))
UpdateState(state, success);
}
DCHECK(InRange(start, end, last_state_.get_offset) ||
last_state_.error != gpu::error::kNoError);
}
void PpapiCommandBufferProxy::SetGetBuffer(int32 transfer_buffer_id) {
......@@ -227,5 +238,15 @@ void PpapiCommandBufferProxy::UpdateState(
}
}
void PpapiCommandBufferProxy::TryUpdateState() {
if (last_state_.error == gpu::error::kNoError)
shared_state()->Read(&last_state_);
}
gpu::CommandBufferSharedState* PpapiCommandBufferProxy::shared_state() const {
return reinterpret_cast<gpu::CommandBufferSharedState*>(
shared_state_shm_->memory());
}
} // namespace proxy
} // namespace ppapi
......@@ -7,8 +7,10 @@
#include "base/callback.h"
#include "base/containers/hash_tables.h"
#include "base/memory/scoped_ptr.h"
#include "gpu/command_buffer/client/gpu_control.h"
#include "gpu/command_buffer/common/command_buffer.h"
#include "gpu/command_buffer/common/command_buffer_shared.h"
#include "ppapi/proxy/ppapi_proxy_export.h"
#include "ppapi/shared_impl/host_resource.h"
......@@ -20,12 +22,14 @@ namespace ppapi {
namespace proxy {
class ProxyChannel;
class SerializedHandle;
class PPAPI_PROXY_EXPORT PpapiCommandBufferProxy : public gpu::CommandBuffer,
public gpu::GpuControl {
public:
PpapiCommandBufferProxy(const HostResource& resource,
ProxyChannel* channel);
ProxyChannel* channel,
const SerializedHandle& shared_state);
virtual ~PpapiCommandBufferProxy();
// gpu::CommandBuffer implementation:
......@@ -63,7 +67,14 @@ class PPAPI_PROXY_EXPORT PpapiCommandBufferProxy : public gpu::CommandBuffer,
bool Send(IPC::Message* msg);
void UpdateState(const gpu::CommandBuffer::State& state, bool success);
// Try to read an updated copy of the state from shared memory.
void TryUpdateState();
// The shared memory area used to update state.
gpu::CommandBufferSharedState* shared_state() const;
State last_state_;
scoped_ptr<base::SharedMemory> shared_state_shm_;
HostResource resource_;
ProxyChannel* channel_;
......
......@@ -868,11 +868,12 @@ IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBCore_ReleaseResource,
ppapi::HostResource)
// PPB_Graphics3D.
IPC_SYNC_MESSAGE_ROUTED3_1(PpapiHostMsg_PPBGraphics3D_Create,
IPC_SYNC_MESSAGE_ROUTED3_2(PpapiHostMsg_PPBGraphics3D_Create,
PP_Instance /* instance */,
ppapi::HostResource /* share_context */,
std::vector<int32_t> /* attrib_list */,
ppapi::HostResource /* result */)
ppapi::HostResource /* result */,
ppapi::proxy::SerializedHandle /* shared_state */)
IPC_SYNC_MESSAGE_ROUTED2_0(PpapiHostMsg_PPBGraphics3D_SetGetBuffer,
ppapi::HostResource /* context */,
int32 /* transfer_buffer_id */)
......
......@@ -28,10 +28,10 @@ namespace {
const int32 kCommandBufferSize = 1024 * 1024;
const int32 kTransferBufferSize = 1024 * 1024;
base::SharedMemoryHandle TransportSHMHandle(Dispatcher* dispatcher,
base::SharedMemory* shm) {
base::PlatformFile source =
IPC::PlatformFileForTransitToPlatformFile(shm->handle());
base::SharedMemoryHandle TransportSHMHandle(
Dispatcher* dispatcher,
const base::SharedMemoryHandle& handle) {
base::PlatformFile source = IPC::PlatformFileForTransitToPlatformFile(handle);
// Don't close the handle, it doesn't belong to us.
return dispatcher->ShareHandleWithRemote(source, false);
}
......@@ -52,13 +52,14 @@ Graphics3D::~Graphics3D() {
DestroyGLES2Impl();
}
bool Graphics3D::Init(gpu::gles2::GLES2Implementation* share_gles2) {
bool Graphics3D::Init(gpu::gles2::GLES2Implementation* share_gles2,
const SerializedHandle& shared_state) {
PluginDispatcher* dispatcher = PluginDispatcher::GetForResource(this);
if (!dispatcher)
return false;
command_buffer_.reset(
new PpapiCommandBufferProxy(host_resource(), dispatcher));
new PpapiCommandBufferProxy(host_resource(), dispatcher, shared_state));
return CreateGLES2Impl(kCommandBufferSize, kTransferBufferSize,
share_gles2);
......@@ -167,13 +168,15 @@ PP_Resource PPB_Graphics3D_Proxy::CreateProxyResource(
attribs.push_back(PP_GRAPHICS3DATTRIB_NONE);
HostResource result;
dispatcher->Send(new PpapiHostMsg_PPBGraphics3D_Create(
API_ID_PPB_GRAPHICS_3D, instance, share_host, attribs, &result));
ppapi::proxy::SerializedHandle shared_state;
dispatcher->Send(new PpapiHostMsg_PPBGraphics3D_Create(API_ID_PPB_GRAPHICS_3D,
instance, share_host, attribs, &result, &shared_state));
if (result.is_null())
return 0;
scoped_refptr<Graphics3D> graphics_3d(new Graphics3D(result));
if (!graphics_3d->Init(share_gles2))
if (!graphics_3d->Init(share_gles2, shared_state))
return 0;
return graphics_3d->GetReference();
}
......@@ -218,7 +221,9 @@ bool PPB_Graphics3D_Proxy::OnMessageReceived(const IPC::Message& msg) {
void PPB_Graphics3D_Proxy::OnMsgCreate(PP_Instance instance,
HostResource share_context,
const std::vector<int32_t>& attribs,
HostResource* result) {
HostResource* result,
SerializedHandle* shared_state) {
shared_state->set_null_shmem();
if (attribs.empty() ||
attribs.back() != PP_GRAPHICS3DATTRIB_NONE ||
!(attribs.size() & 1))
......@@ -226,12 +231,19 @@ void PPB_Graphics3D_Proxy::OnMsgCreate(PP_Instance instance,
thunk::EnterResourceCreation enter(instance);
if (enter.succeeded()) {
result->SetHostResource(
if (!enter.succeeded())
return;
base::SharedMemoryHandle handle = IPC::InvalidPlatformFileForTransit();
result->SetHostResource(
instance,
enter.functions()->CreateGraphics3DRaw(instance,
share_context.host_resource(),
&attribs.front()));
&attribs.front(),
&handle));
if (!result->is_null()) {
shared_state->set_shmem(TransportSHMHandle(dispatcher(), handle),
sizeof(gpu::CommandBuffer::State));
}
}
......@@ -284,7 +296,7 @@ void PPB_Graphics3D_Proxy::OnMsgCreateTransferBuffer(
const HostResource& context,
uint32 size,
int32* id,
ppapi::proxy::SerializedHandle* transfer_buffer) {
SerializedHandle* transfer_buffer) {
transfer_buffer->set_null_shmem();
EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
if (enter.succeeded()) {
......@@ -296,7 +308,7 @@ void PPB_Graphics3D_Proxy::OnMsgCreateTransferBuffer(
static_cast<gpu::SharedMemoryBufferBacking*>(buffer->backing());
DCHECK(backing && backing->shared_memory());
transfer_buffer->set_shmem(
TransportSHMHandle(dispatcher(), backing->shared_memory()),
TransportSHMHandle(dispatcher(), backing->shared_memory()->handle()),
buffer->size());
} else {
*id = -1;
......
......@@ -32,7 +32,8 @@ class PPAPI_PROXY_EXPORT Graphics3D : public PPB_Graphics3D_Shared {
explicit Graphics3D(const HostResource& resource);
virtual ~Graphics3D();
bool Init(gpu::gles2::GLES2Implementation* share_gles2);
bool Init(gpu::gles2::GLES2Implementation* share_gles2,
const SerializedHandle& shared_state);
// Graphics3DTrusted API. These are not implemented in the proxy.
virtual PP_Bool SetGetBuffer(int32_t shm_id) OVERRIDE;
......@@ -79,7 +80,8 @@ class PPB_Graphics3D_Proxy : public InterfaceProxy {
void OnMsgCreate(PP_Instance instance,
HostResource share_context,
const std::vector<int32_t>& attribs,
HostResource* result);
HostResource* result,
SerializedHandle* handle);
void OnMsgSetGetBuffer(const HostResource& context,
int32 id);
void OnMsgWaitForTokenInRange(const HostResource& context,
......
......@@ -252,7 +252,8 @@ PP_Resource ResourceCreationProxy::CreateGraphics3D(
PP_Resource ResourceCreationProxy::CreateGraphics3DRaw(
PP_Instance instance,
PP_Resource share_context,
const int32_t* attrib_list) {
const int32_t* attrib_list,
base::SharedMemoryHandle* shared_state) {
// Not proxied. The raw creation function is used only in the implementation
// of the proxy on the host side.
return 0;
......
......@@ -119,7 +119,8 @@ class ResourceCreationProxy : public InterfaceProxy,
virtual PP_Resource CreateGraphics3DRaw(
PP_Instance instance,
PP_Resource share_context,
const int32_t* attrib_list) OVERRIDE;
const int32_t* attrib_list,
base::SharedMemoryHandle* shared_state) OVERRIDE;
virtual PP_Resource CreateHostResolver(PP_Instance instance) OVERRIDE;
virtual PP_Resource CreateHostResolverPrivate(PP_Instance instance) OVERRIDE;
virtual PP_Resource CreateImageData(PP_Instance instance,
......
......@@ -5,6 +5,7 @@
#ifndef PPAPI_THUNK_RESOURCE_CREATION_API_H_
#define PPAPI_THUNK_RESOURCE_CREATION_API_H_
#include "base/memory/shared_memory.h"
#include "ppapi/c/dev/pp_video_dev.h"
#include "ppapi/c/dev/ppb_file_chooser_dev.h"
#include "ppapi/c/dev/ppb_truetype_font_dev.h"
......@@ -129,9 +130,11 @@ class ResourceCreationAPI {
virtual PP_Resource CreateGraphics3D(PP_Instance instance,
PP_Resource share_context,
const int32_t* attrib_list) = 0;
virtual PP_Resource CreateGraphics3DRaw(PP_Instance instance,
PP_Resource share_context,
const int32_t* attrib_list) = 0;
virtual PP_Resource CreateGraphics3DRaw(
PP_Instance instance,
PP_Resource share_context,
const int32_t* attrib_list,
base::SharedMemoryHandle* shared_state) = 0;
virtual PP_Resource CreateHostResolver(PP_Instance instance) = 0;
virtual PP_Resource CreateHostResolverPrivate(PP_Instance instance) = 0;
virtual PP_Resource CreateImageData(PP_Instance instance,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment