diff options
Diffstat (limited to 'ppapi/proxy/ppb_surface_3d_proxy.cc')
-rw-r--r-- | ppapi/proxy/ppb_surface_3d_proxy.cc | 210 |
1 files changed, 210 insertions, 0 deletions
diff --git a/ppapi/proxy/ppb_surface_3d_proxy.cc b/ppapi/proxy/ppb_surface_3d_proxy.cc new file mode 100644 index 0000000..c0288d0 --- /dev/null +++ b/ppapi/proxy/ppb_surface_3d_proxy.cc @@ -0,0 +1,210 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ppapi/proxy/ppb_surface_3d_proxy.h" + +#include "gpu/command_buffer/client/gles2_implementation.h" +#include "ppapi/c/pp_errors.h" +#include "ppapi/c/pp_resource.h" +#include "ppapi/c/dev/ppb_surface_3d_dev.h" +#include "ppapi/proxy/enter_proxy.h" +#include "ppapi/proxy/plugin_dispatcher.h" +#include "ppapi/proxy/plugin_resource.h" +#include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/proxy/ppb_context_3d_proxy.h" +#include "ppapi/thunk/enter.h" +#include "ppapi/thunk/resource_creation_api.h" +#include "ppapi/thunk/thunk.h" + +using ppapi::thunk::EnterFunctionNoLock; +using ppapi::thunk::PPB_Surface3D_API; +using ppapi::thunk::ResourceCreationAPI; + +namespace pp { +namespace proxy { + +namespace { + +InterfaceProxy* CreateSurface3DProxy(Dispatcher* dispatcher, + const void* target_interface) { + return new PPB_Surface3D_Proxy(dispatcher, target_interface); +} + +} // namespace + +// Surface3D ------------------------------------------------------------------- + +Surface3D::Surface3D(const HostResource& host_resource) + : PluginResource(host_resource), + resource_(0), + context_(NULL), + current_flush_callback_(PP_BlockUntilComplete()) { +} + +Surface3D::~Surface3D() { + if (context_) + context_->BindSurfaces(0, 0); +} + +PPB_Surface3D_API* Surface3D::AsPPB_Surface3D_API() { + return this; +} + +int32_t Surface3D::SetAttrib(int32_t attribute, int32_t value) { + // TODO(alokp): Implement me. + return 0; +} + +int32_t Surface3D::GetAttrib(int32_t attribute, int32_t* value) { + // TODO(alokp): Implement me. + return 0; +} + +int32_t Surface3D::SwapBuffers(PP_CompletionCallback callback) { + // For now, disallow blocking calls. We'll need to add support for other + // threads to this later. + if (!callback.func) + return PP_ERROR_BADARGUMENT; + + if (is_flush_pending()) + return PP_ERROR_INPROGRESS; // Can't have >1 flush pending. + + if (!context_) + return PP_ERROR_FAILED; + + current_flush_callback_ = callback; + + IPC::Message* msg = new PpapiHostMsg_PPBSurface3D_SwapBuffers( + INTERFACE_ID_PPB_SURFACE_3D, host_resource()); + msg->set_unblock(true); + GetDispatcher()->Send(msg); + + context_->gles2_impl()->SwapBuffers(); + return PP_OK_COMPLETIONPENDING; +} + +void Surface3D::SwapBuffersACK(int32_t pp_error) { + PP_RunAndClearCompletionCallback(¤t_flush_callback_, pp_error); +} + +// PPB_Surface3D_Proxy --------------------------------------------------------- + +PPB_Surface3D_Proxy::PPB_Surface3D_Proxy(Dispatcher* dispatcher, + const void* target_interface) + : InterfaceProxy(dispatcher, target_interface), + callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { +} + +PPB_Surface3D_Proxy::~PPB_Surface3D_Proxy() { +} + +// static +const InterfaceProxy::Info* PPB_Surface3D_Proxy::GetInfo() { + static const Info info = { + ::ppapi::thunk::GetPPB_Surface3D_Thunk(), + PPB_SURFACE_3D_DEV_INTERFACE, + INTERFACE_ID_PPB_SURFACE_3D, + false, + &CreateSurface3DProxy, + }; + return &info; +} + +// static +PP_Resource PPB_Surface3D_Proxy::CreateProxyResource( + PP_Instance instance, + PP_Config3D_Dev config, + const int32_t* attrib_list) { + PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance); + if (!dispatcher) + return PP_ERROR_BADARGUMENT; + + std::vector<int32_t> attribs; + if (attrib_list) { + const int32_t* attr = attrib_list; + while(*attr != PP_GRAPHICS3DATTRIB_NONE) { + attribs.push_back(*(attr++)); // Attribute. + attribs.push_back(*(attr++)); // Value. + } + } + attribs.push_back(PP_GRAPHICS3DATTRIB_NONE); // Always terminate. + + HostResource result; + dispatcher->Send(new PpapiHostMsg_PPBSurface3D_Create( + INTERFACE_ID_PPB_SURFACE_3D, instance, config, attribs, &result)); + + if (result.is_null()) + return 0; + linked_ptr<Surface3D> surface_3d(new Surface3D(result)); + PP_Resource resource = + PluginResourceTracker::GetInstance()->AddResource(surface_3d); + surface_3d->set_resource(resource); + return resource; +} + +bool PPB_Surface3D_Proxy::OnMessageReceived(const IPC::Message& msg) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(PPB_Surface3D_Proxy, msg) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBSurface3D_Create, + OnMsgCreate) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBSurface3D_SwapBuffers, + OnMsgSwapBuffers) + + IPC_MESSAGE_HANDLER(PpapiMsg_PPBSurface3D_SwapBuffersACK, + OnMsgSwapBuffersACK) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + // FIXME(brettw) handle bad messages! + return handled; +} + +void PPB_Surface3D_Proxy::OnMsgCreate(PP_Instance instance, + PP_Config3D_Dev config, + const std::vector<int32_t>& attribs, + HostResource* result) { + if (attribs.empty() || + attribs.size() % 2 != 1 || + attribs.back() != PP_GRAPHICS3DATTRIB_NONE) + return; // Bad message. + + EnterFunctionNoLock<ResourceCreationAPI> enter(instance, true); + if (enter.succeeded()) { + result->SetHostResource( + instance, + enter.functions()->CreateSurface3D(instance, config, &attribs.front())); + } +} + +void PPB_Surface3D_Proxy::OnMsgSwapBuffers(const HostResource& surface_3d) { + CompletionCallback callback = callback_factory_.NewOptionalCallback( + &PPB_Surface3D_Proxy::SendSwapBuffersACKToPlugin, surface_3d); + + EnterHostFromHostResource<PPB_Surface3D_API> enter(surface_3d); + int32_t result = PP_ERROR_BADRESOURCE; + if (enter.succeeded()) + result = enter.object()->SwapBuffers(callback.pp_completion_callback()); + if (result != PP_OK_COMPLETIONPENDING) { + // There was some error, so we won't get a flush callback. We need to now + // issue the ACK to the plugin hears about the error. This will also clean + // up the data associated with the callback. + callback.Run(result); + } +} + +void PPB_Surface3D_Proxy::OnMsgSwapBuffersACK(const HostResource& resource, + int32_t pp_error) { + EnterPluginFromHostResource<PPB_Surface3D_API> enter(resource); + if (enter.succeeded()) + static_cast<Surface3D*>(enter.object())->SwapBuffersACK(pp_error); +} + +void PPB_Surface3D_Proxy::SendSwapBuffersACKToPlugin( + int32_t result, + const HostResource& surface_3d) { + dispatcher()->Send(new PpapiMsg_PPBSurface3D_SwapBuffersACK( + INTERFACE_ID_PPB_SURFACE_3D, surface_3d, result)); +} + +} // namespace proxy +} // namespace pp |