// 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 "ppapi/proxy/compositor_resource.h" #include "base/logging.h" #include "ppapi/proxy/ppapi_messages.h" #include "ppapi/thunk/enter.h" namespace ppapi { namespace proxy { CompositorResource::CompositorResource(Connection connection, PP_Instance instance) : PluginResource(connection, instance), layer_reset_(true), last_resource_id_(0) { SendCreate(RENDERER, PpapiHostMsg_Compositor_Create()); } bool CompositorResource::IsInProgress() const { ProxyLock::AssertAcquiredDebugOnly(); return TrackedCallback::IsPending(commit_callback_); } int32_t CompositorResource::GenerateResourceId() const { ProxyLock::AssertAcquiredDebugOnly(); return ++last_resource_id_; } CompositorResource::~CompositorResource() { ResetLayersInternal(true); // Abort all release callbacks. for (ReleaseCallbackMap::iterator it = release_callback_map_.begin(); it != release_callback_map_.end(); ++it) { if (!it->second.is_null()) it->second.Run(PP_ERROR_ABORTED, 0, false); } } thunk::PPB_Compositor_API* CompositorResource::AsPPB_Compositor_API() { return this; } void CompositorResource::OnReplyReceived( const ResourceMessageReplyParams& params, const IPC::Message& msg) { PPAPI_BEGIN_MESSAGE_MAP(CompositorResource, msg) PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL( PpapiPluginMsg_Compositor_ReleaseResource, OnPluginMsgReleaseResource) PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL_UNHANDLED( PluginResource::OnReplyReceived(params, msg)) PPAPI_END_MESSAGE_MAP() } PP_Resource CompositorResource::AddLayer() { scoped_refptr resource(new CompositorLayerResource( connection(), pp_instance(), this)); layers_.push_back(resource); return resource->GetReference(); } int32_t CompositorResource::CommitLayers( const scoped_refptr& callback) { if (IsInProgress()) return PP_ERROR_INPROGRESS; std::vector layers; layers.reserve(layers_.size()); for (LayerList::const_iterator it = layers_.begin(); it != layers_.end(); ++it) { if ((*it)->data().is_null()) return PP_ERROR_FAILED; layers.push_back((*it)->data()); } commit_callback_ = callback; Call( RENDERER, PpapiHostMsg_Compositor_CommitLayers(layers, layer_reset_), base::Bind(&CompositorResource::OnPluginMsgCommitLayersReply, base::Unretained(this)), callback); return PP_OK_COMPLETIONPENDING; } int32_t CompositorResource::ResetLayers() { if (IsInProgress()) return PP_ERROR_INPROGRESS; ResetLayersInternal(false); return PP_OK; } void CompositorResource::OnPluginMsgCommitLayersReply( const ResourceMessageReplyParams& params) { if (!TrackedCallback::IsPending(commit_callback_)) return; // On success, we put layers' release_callbacks into a map, // otherwise we will do nothing. So plugin may change layers and // call CommitLayers() again. if (params.result() == PP_OK) { layer_reset_ = false; for (LayerList::iterator it = layers_.begin(); it != layers_.end(); ++it) { ReleaseCallback release_callback = (*it)->release_callback(); if (!release_callback.is_null()) { release_callback_map_.insert(ReleaseCallbackMap::value_type( (*it)->data().common.resource_id, release_callback)); (*it)->ResetReleaseCallback(); } } } scoped_refptr callback; callback.swap(commit_callback_); callback->Run(params.result()); } void CompositorResource::OnPluginMsgReleaseResource( const ResourceMessageReplyParams& params, int32_t id, uint32_t sync_point, bool is_lost) { ReleaseCallbackMap::iterator it = release_callback_map_.find(id); DCHECK(it != release_callback_map_.end()) << "Can not found release_callback_ by id(" << id << ")!"; it->second.Run(PP_OK, sync_point, is_lost); release_callback_map_.erase(it); } void CompositorResource::ResetLayersInternal(bool is_aborted) { for (LayerList::iterator it = layers_.begin(); it != layers_.end(); ++it) { ReleaseCallback release_callback = (*it)->release_callback(); if (!release_callback.is_null()) { release_callback.Run(is_aborted ? PP_ERROR_ABORTED : PP_OK, 0, false); (*it)->ResetReleaseCallback(); } (*it)->Invalidate(); } layers_.clear(); layer_reset_ = true; } } // namespace proxy } // namespace ppapi