| // 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<CompositorLayerResource> resource(new CompositorLayerResource( |
| connection(), pp_instance(), this)); |
| layers_.push_back(resource); |
| return resource->GetReference(); |
| } |
| |
| int32_t CompositorResource::CommitLayers( |
| const scoped_refptr<ppapi::TrackedCallback>& callback) { |
| if (IsInProgress()) |
| return PP_ERROR_INPROGRESS; |
| |
| std::vector<CompositorLayerData> 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<PpapiPluginMsg_Compositor_CommitLayersReply>( |
| 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<TrackedCallback> 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 |