• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
CompositorResource(Connection connection,PP_Instance instance)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 
IsInProgress() const22 bool CompositorResource::IsInProgress() const {
23   ProxyLock::AssertAcquiredDebugOnly();
24   return TrackedCallback::IsPending(commit_callback_);
25 }
26 
GenerateResourceId() const27 int32_t CompositorResource::GenerateResourceId() const {
28   ProxyLock::AssertAcquiredDebugOnly();
29   return ++last_resource_id_;
30 }
31 
~CompositorResource()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 
AsPPB_Compositor_API()43 thunk::PPB_Compositor_API* CompositorResource::AsPPB_Compositor_API() {
44   return this;
45 }
46 
OnReplyReceived(const ResourceMessageReplyParams & params,const IPC::Message & msg)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 
AddLayer()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 
CommitLayers(const scoped_refptr<ppapi::TrackedCallback> & callback)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 
ResetLayers()92 int32_t CompositorResource::ResetLayers() {
93   if (IsInProgress())
94     return PP_ERROR_INPROGRESS;
95 
96   ResetLayersInternal(false);
97   return PP_OK;
98 }
99 
OnPluginMsgCommitLayersReply(const ResourceMessageReplyParams & params)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 
OnPluginMsgReleaseResource(const ResourceMessageReplyParams & params,int32_t id,uint32_t sync_point,bool is_lost)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 
ResetLayersInternal(bool is_aborted)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