OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2011 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/ppb_surface_3d_proxy.h" |
| 6 |
| 7 #include "gpu/command_buffer/client/gles2_implementation.h" |
| 8 #include "ppapi/c/pp_errors.h" |
| 9 #include "ppapi/c/pp_resource.h" |
| 10 #include "ppapi/c/dev/ppb_surface_3d_dev.h" |
| 11 #include "ppapi/proxy/plugin_dispatcher.h" |
| 12 #include "ppapi/proxy/plugin_resource.h" |
| 13 #include "ppapi/proxy/ppapi_messages.h" |
| 14 #include "ppapi/proxy/ppb_context_3d_proxy.h" |
| 15 |
| 16 namespace pp { |
| 17 namespace proxy { |
| 18 |
| 19 namespace { |
| 20 |
| 21 PP_Resource Create(PP_Instance instance, |
| 22 PP_Config3D_Dev config, |
| 23 const int32_t* attrib_list) { |
| 24 PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance); |
| 25 if (!dispatcher) |
| 26 return PP_ERROR_BADARGUMENT; |
| 27 |
| 28 std::vector<int32_t> attribs; |
| 29 if (attrib_list) { |
| 30 for (const int32_t* attr = attrib_list; attr; ++attr) |
| 31 attribs.push_back(*attr); |
| 32 } else { |
| 33 attribs.push_back(0); |
| 34 } |
| 35 |
| 36 HostResource result; |
| 37 dispatcher->Send(new PpapiHostMsg_PPBSurface3D_Create( |
| 38 INTERFACE_ID_PPB_SURFACE_3D, instance, config, attribs, &result)); |
| 39 |
| 40 if (result.is_null()) |
| 41 return 0; |
| 42 linked_ptr<Surface3D> surface_3d(new Surface3D(result)); |
| 43 PP_Resource resource = |
| 44 PluginResourceTracker::GetInstance()->AddResource(surface_3d); |
| 45 surface_3d->set_resource(resource); |
| 46 return resource; |
| 47 } |
| 48 |
| 49 PP_Bool IsSurface3D(PP_Resource resource) { |
| 50 Surface3D* object = PluginResource::GetAs<Surface3D>(resource); |
| 51 return BoolToPPBool(!!object); |
| 52 } |
| 53 |
| 54 int32_t SetAttrib(PP_Resource surface_id, |
| 55 int32_t attribute, |
| 56 int32_t value) { |
| 57 // TODO(alokp): Implement me. |
| 58 return 0; |
| 59 } |
| 60 |
| 61 int32_t GetAttrib(PP_Resource surface_id, |
| 62 int32_t attribute, |
| 63 int32_t* value) { |
| 64 // TODO(alokp): Implement me. |
| 65 return 0; |
| 66 } |
| 67 |
| 68 int32_t SwapBuffers(PP_Resource surface_id, |
| 69 PP_CompletionCallback callback) { |
| 70 Surface3D* object = PluginResource::GetAs<Surface3D>(surface_id); |
| 71 if (!object) |
| 72 return PP_ERROR_BADRESOURCE; |
| 73 PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance( |
| 74 object->instance()); |
| 75 if (!dispatcher) |
| 76 return PP_ERROR_FAILED; |
| 77 |
| 78 // For now, disallow blocking calls. We'll need to add support for other |
| 79 // threads to this later. |
| 80 if (!callback.func) |
| 81 return PP_ERROR_BADARGUMENT; |
| 82 |
| 83 if (object->is_flush_pending()) |
| 84 return PP_ERROR_INPROGRESS; // Can't have >1 flush pending. |
| 85 |
| 86 if (!object->context()) |
| 87 return PP_ERROR_FAILED; |
| 88 |
| 89 object->set_current_flush_callback(callback); |
| 90 |
| 91 IPC::Message* msg = new PpapiHostMsg_PPBSurface3D_SwapBuffers( |
| 92 INTERFACE_ID_PPB_SURFACE_3D, object->host_resource()); |
| 93 msg->set_unblock(true); |
| 94 dispatcher->Send(msg); |
| 95 |
| 96 object->context()->gles2_impl()->SwapBuffers(); |
| 97 |
| 98 return PP_ERROR_WOULDBLOCK; |
| 99 } |
| 100 |
| 101 const PPB_Surface3D_Dev ppb_surface_3d = { |
| 102 &Create, |
| 103 &IsSurface3D, |
| 104 &SetAttrib, |
| 105 &GetAttrib, |
| 106 &SwapBuffers |
| 107 }; |
| 108 |
| 109 } // namespace |
| 110 |
| 111 PPB_Surface3D_Proxy::PPB_Surface3D_Proxy(Dispatcher* dispatcher, |
| 112 const void* target_interface) |
| 113 : InterfaceProxy(dispatcher, target_interface), |
| 114 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { |
| 115 } |
| 116 |
| 117 PPB_Surface3D_Proxy::~PPB_Surface3D_Proxy() { |
| 118 } |
| 119 |
| 120 const void* PPB_Surface3D_Proxy::GetSourceInterface() const { |
| 121 return &ppb_surface_3d; |
| 122 } |
| 123 |
| 124 InterfaceID PPB_Surface3D_Proxy::GetInterfaceId() const { |
| 125 return INTERFACE_ID_PPB_SURFACE_3D; |
| 126 } |
| 127 |
| 128 bool PPB_Surface3D_Proxy::OnMessageReceived(const IPC::Message& msg) { |
| 129 bool handled = true; |
| 130 IPC_BEGIN_MESSAGE_MAP(PPB_Surface3D_Proxy, msg) |
| 131 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBSurface3D_Create, |
| 132 OnMsgCreate) |
| 133 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBSurface3D_SwapBuffers, |
| 134 OnMsgSwapBuffers) |
| 135 |
| 136 IPC_MESSAGE_HANDLER(PpapiMsg_PPBSurface3D_SwapBuffersACK, |
| 137 OnMsgSwapBuffersACK) |
| 138 IPC_MESSAGE_UNHANDLED(handled = false) |
| 139 IPC_END_MESSAGE_MAP() |
| 140 // FIXME(brettw) handle bad messages! |
| 141 return handled; |
| 142 } |
| 143 |
| 144 void PPB_Surface3D_Proxy::OnMsgCreate(PP_Instance instance, |
| 145 PP_Config3D_Dev config, |
| 146 std::vector<int32_t> attribs, |
| 147 HostResource* result) { |
| 148 DCHECK(attribs.back() == 0); |
| 149 PP_Resource resource = |
| 150 ppb_surface_3d_target()->Create(instance, config, &attribs.front()); |
| 151 result->SetHostResource(instance, resource); |
| 152 } |
| 153 |
| 154 void PPB_Surface3D_Proxy::OnMsgSwapBuffers(const HostResource& surface_3d) { |
| 155 CompletionCallback callback = callback_factory_.NewCallback( |
| 156 &PPB_Surface3D_Proxy::SendSwapBuffersACKToPlugin, surface_3d); |
| 157 int32_t result = ppb_surface_3d_target()->SwapBuffers( |
| 158 surface_3d.host_resource(), callback.pp_completion_callback()); |
| 159 if (result != PP_ERROR_WOULDBLOCK) { |
| 160 // There was some error, so we won't get a flush callback. We need to now |
| 161 // issue the ACK to the plugin hears about the error. This will also clean |
| 162 // up the data associated with the callback. |
| 163 callback.Run(result); |
| 164 } |
| 165 } |
| 166 |
| 167 void PPB_Surface3D_Proxy::OnMsgSwapBuffersACK(const HostResource& resource, |
| 168 int32_t pp_error) { |
| 169 PP_Resource plugin_resource = |
| 170 PluginResourceTracker::GetInstance()->PluginResourceForHostResource( |
| 171 resource); |
| 172 if (!plugin_resource) |
| 173 return; |
| 174 Surface3D* object = PluginResource::GetAs<Surface3D>(plugin_resource); |
| 175 if (!object) { |
| 176 // The plugin has released the Surface3D object so don't issue the |
| 177 // callback. |
| 178 return; |
| 179 } |
| 180 |
| 181 // Be careful to make the callback NULL again before issuing the callback |
| 182 // since the plugin might want to flush from within the callback. |
| 183 PP_CompletionCallback callback = object->current_flush_callback(); |
| 184 object->set_current_flush_callback(PP_BlockUntilComplete()); |
| 185 PP_RunCompletionCallback(&callback, pp_error); |
| 186 } |
| 187 |
| 188 void PPB_Surface3D_Proxy::SendSwapBuffersACKToPlugin( |
| 189 int32_t result, |
| 190 const HostResource& surface_3d) { |
| 191 dispatcher()->Send(new PpapiMsg_PPBSurface3D_SwapBuffersACK( |
| 192 INTERFACE_ID_PPB_SURFACE_3D, surface_3d, result)); |
| 193 } |
| 194 |
| 195 } // namespace proxy |
| 196 } // namespace pp |
OLD | NEW |