1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "ppapi/proxy/compositor_resource.h" 6 7 #include "base/logging.h" 8 #include "ppapi/proxy/ppapi_messages.h" 9 #include "ppapi/thunk/enter.h" 10 11 namespace ppapi { 12 namespace proxy { 13 14 CompositorResource::CompositorResource(Connection connection, 15 PP_Instance instance) 16 : PluginResource(connection, instance), 17 layer_reset_(true), 18 last_resource_id_(0) { 19 SendCreate(RENDERER, PpapiHostMsg_Compositor_Create()); 20 } 21 22 bool CompositorResource::IsInProgress() const { 23 ProxyLock::AssertAcquiredDebugOnly(); 24 return TrackedCallback::IsPending(commit_callback_); 25 } 26 27 int32_t CompositorResource::GenerateResourceId() const { 28 ProxyLock::AssertAcquiredDebugOnly(); 29 return ++last_resource_id_; 30 } 31 32 CompositorResource::~CompositorResource() { 33 ResetLayersInternal(true); 34 35 // Abort all release callbacks. 36 for (ReleaseCallbackMap::iterator it = release_callback_map_.begin(); 37 it != release_callback_map_.end(); ++it) { 38 if (!it->second.is_null()) 39 it->second.Run(PP_ERROR_ABORTED, 0, false); 40 } 41 } 42 43 thunk::PPB_Compositor_API* CompositorResource::AsPPB_Compositor_API() { 44 return this; 45 } 46 47 void CompositorResource::OnReplyReceived( 48 const ResourceMessageReplyParams& params, 49 const IPC::Message& msg) { 50 PPAPI_BEGIN_MESSAGE_MAP(CompositorResource, msg) 51 PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL( 52 PpapiPluginMsg_Compositor_ReleaseResource, 53 OnPluginMsgReleaseResource) 54 PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL_UNHANDLED( 55 PluginResource::OnReplyReceived(params, msg)) 56 PPAPI_END_MESSAGE_MAP() 57 } 58 59 PP_Resource CompositorResource::AddLayer() { 60 scoped_refptr<CompositorLayerResource> resource(new CompositorLayerResource( 61 connection(), pp_instance(), this)); 62 layers_.push_back(resource); 63 return resource->GetReference(); 64 } 65 66 int32_t CompositorResource::CommitLayers( 67 const scoped_refptr<ppapi::TrackedCallback>& callback) { 68 if (IsInProgress()) 69 return PP_ERROR_INPROGRESS; 70 71 std::vector<CompositorLayerData> layers; 72 layers.reserve(layers_.size()); 73 74 for (LayerList::const_iterator it = layers_.begin(); 75 it != layers_.end(); ++it) { 76 if ((*it)->data().is_null()) 77 return PP_ERROR_FAILED; 78 layers.push_back((*it)->data()); 79 } 80 81 commit_callback_ = callback; 82 Call<PpapiPluginMsg_Compositor_CommitLayersReply>( 83 RENDERER, 84 PpapiHostMsg_Compositor_CommitLayers(layers, layer_reset_), 85 base::Bind(&CompositorResource::OnPluginMsgCommitLayersReply, 86 base::Unretained(this)), 87 callback); 88 89 return PP_OK_COMPLETIONPENDING; 90 } 91 92 int32_t CompositorResource::ResetLayers() { 93 if (IsInProgress()) 94 return PP_ERROR_INPROGRESS; 95 96 ResetLayersInternal(false); 97 return PP_OK; 98 } 99 100 void CompositorResource::OnPluginMsgCommitLayersReply( 101 const ResourceMessageReplyParams& params) { 102 if (!TrackedCallback::IsPending(commit_callback_)) 103 return; 104 105 // On success, we put layers' release_callbacks into a map, 106 // otherwise we will do nothing. So plugin may change layers and 107 // call CommitLayers() again. 108 if (params.result() == PP_OK) { 109 layer_reset_ = false; 110 for (LayerList::iterator it = layers_.begin(); 111 it != layers_.end(); ++it) { 112 ReleaseCallback release_callback = (*it)->release_callback(); 113 if (!release_callback.is_null()) { 114 release_callback_map_.insert(ReleaseCallbackMap::value_type( 115 (*it)->data().common.resource_id, release_callback)); 116 (*it)->ResetReleaseCallback(); 117 } 118 } 119 } 120 121 scoped_refptr<TrackedCallback> callback; 122 callback.swap(commit_callback_); 123 callback->Run(params.result()); 124 } 125 126 void CompositorResource::OnPluginMsgReleaseResource( 127 const ResourceMessageReplyParams& params, 128 int32_t id, 129 uint32_t sync_point, 130 bool is_lost) { 131 ReleaseCallbackMap::iterator it = release_callback_map_.find(id); 132 DCHECK(it != release_callback_map_.end()) << 133 "Can not found release_callback_ by id(" << id << ")!"; 134 it->second.Run(PP_OK, sync_point, is_lost); 135 release_callback_map_.erase(it); 136 } 137 138 void CompositorResource::ResetLayersInternal(bool is_aborted) { 139 for (LayerList::iterator it = layers_.begin(); 140 it != layers_.end(); ++it) { 141 ReleaseCallback release_callback = (*it)->release_callback(); 142 if (!release_callback.is_null()) { 143 release_callback.Run(is_aborted ? PP_ERROR_ABORTED : PP_OK, 0, false); 144 (*it)->ResetReleaseCallback(); 145 } 146 (*it)->Invalidate(); 147 } 148 149 layers_.clear(); 150 layer_reset_ = true; 151 } 152 153 } // namespace proxy 154 } // namespace ppapi 155