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