Home | History | Annotate | Download | only in proxy
      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