diff options
author | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-25 02:23:05 +0000 |
---|---|---|
committer | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-25 02:23:05 +0000 |
commit | 20790a2251838ef5d3f2432ba6f0c9f54e7c7838 (patch) | |
tree | a54762e7c5803efc7955c709eade6c541c18a804 /content/renderer/pepper/ppb_graphics_3d_impl.cc | |
parent | 64974bea71a5c4cf95e67afef2e121e04af451f4 (diff) | |
download | chromium_src-20790a2251838ef5d3f2432ba6f0c9f54e7c7838.zip chromium_src-20790a2251838ef5d3f2432ba6f0c9f54e7c7838.tar.gz chromium_src-20790a2251838ef5d3f2432ba6f0c9f54e7c7838.tar.bz2 |
Move webkit/plugins/ppapi to content/renderer/pepper.
I will change namespaces in a followup as this got very large. Also, I have a temporary dependency from content/common onto content/renderer for PluginModule that I only discovered at the end. I will remove that in a followup.
BUG=263054
R=scottmg@chromium.org
Review URL: https://codereview.chromium.org/20165002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@213578 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/renderer/pepper/ppb_graphics_3d_impl.cc')
-rw-r--r-- | content/renderer/pepper/ppb_graphics_3d_impl.cc | 328 |
1 files changed, 328 insertions, 0 deletions
diff --git a/content/renderer/pepper/ppb_graphics_3d_impl.cc b/content/renderer/pepper/ppb_graphics_3d_impl.cc new file mode 100644 index 0000000..26a7789 --- /dev/null +++ b/content/renderer/pepper/ppb_graphics_3d_impl.cc @@ -0,0 +1,328 @@ +// Copyright (c) 2012 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 "content/renderer/pepper/ppb_graphics_3d_impl.h" + +#include "base/bind.h" +#include "base/command_line.h" +#include "base/message_loop/message_loop.h" +#include "base/strings/utf_string_conversions.h" +#include "content/renderer/pepper/plugin_module.h" +#include "content/renderer/pepper/ppapi_plugin_instance_impl.h" +#include "content/renderer/pepper/resource_helper.h" +#include "gpu/command_buffer/client/gles2_implementation.h" +#include "ppapi/c/ppp_graphics_3d.h" +#include "ppapi/thunk/enter.h" +#include "third_party/WebKit/public/platform/WebString.h" +#include "third_party/WebKit/public/web/WebConsoleMessage.h" +#include "third_party/WebKit/public/web/WebDocument.h" +#include "third_party/WebKit/public/web/WebElement.h" +#include "third_party/WebKit/public/web/WebFrame.h" +#include "third_party/WebKit/public/web/WebPluginContainer.h" +#include "webkit/plugins/plugin_switches.h" + +using ppapi::thunk::EnterResourceNoLock; +using ppapi::thunk::PPB_Graphics3D_API; +using WebKit::WebConsoleMessage; +using WebKit::WebFrame; +using WebKit::WebPluginContainer; +using WebKit::WebString; + +namespace webkit { +namespace ppapi { + +namespace { +const int32 kCommandBufferSize = 1024 * 1024; +const int32 kTransferBufferSize = 1024 * 1024; + +PP_Bool ShmToHandle(base::SharedMemory* shm, + size_t size, + int* shm_handle, + uint32_t* shm_size) { + if (!shm || !shm_handle || !shm_size) + return PP_FALSE; +#if defined(OS_POSIX) + *shm_handle = shm->handle().fd; +#elif defined(OS_WIN) + *shm_handle = reinterpret_cast<int>(shm->handle()); +#else + #error "Platform not supported." +#endif + *shm_size = size; + return PP_TRUE; +} + +} // namespace. + +PPB_Graphics3D_Impl::PPB_Graphics3D_Impl(PP_Instance instance) + : PPB_Graphics3D_Shared(instance), + bound_to_instance_(false), + commit_pending_(false), + weak_ptr_factory_(this) { +} + +PPB_Graphics3D_Impl::~PPB_Graphics3D_Impl() { + DestroyGLES2Impl(); +} + +// static +PP_Bool PPB_Graphics3D_Impl::IsGpuBlacklisted() { + CommandLine* command_line = CommandLine::ForCurrentProcess(); + if (command_line) + return PP_FromBool( + command_line->HasSwitch(switches::kDisablePepper3d)); + return PP_TRUE; +} + +// static +PP_Resource PPB_Graphics3D_Impl::Create(PP_Instance instance, + PP_Resource share_context, + const int32_t* attrib_list) { + PPB_Graphics3D_API* share_api = NULL; + if (IsGpuBlacklisted()) + return 0; + if (share_context) { + EnterResourceNoLock<PPB_Graphics3D_API> enter(share_context, true); + if (enter.failed()) + return 0; + share_api = enter.object(); + } + scoped_refptr<PPB_Graphics3D_Impl> graphics_3d( + new PPB_Graphics3D_Impl(instance)); + if (!graphics_3d->Init(share_api, attrib_list)) + return 0; + return graphics_3d->GetReference(); +} + +// static +PP_Resource PPB_Graphics3D_Impl::CreateRaw(PP_Instance instance, + PP_Resource share_context, + const int32_t* attrib_list) { + PPB_Graphics3D_API* share_api = NULL; + if (IsGpuBlacklisted()) + return 0; + if (share_context) { + EnterResourceNoLock<PPB_Graphics3D_API> enter(share_context, true); + if (enter.failed()) + return 0; + share_api = enter.object(); + } + scoped_refptr<PPB_Graphics3D_Impl> graphics_3d( + new PPB_Graphics3D_Impl(instance)); + if (!graphics_3d->InitRaw(share_api, attrib_list)) + return 0; + return graphics_3d->GetReference(); +} + +PP_Bool PPB_Graphics3D_Impl::SetGetBuffer(int32_t transfer_buffer_id) { + GetCommandBuffer()->SetGetBuffer(transfer_buffer_id); + return PP_TRUE; +} + +gpu::CommandBuffer::State PPB_Graphics3D_Impl::GetState() { + return GetCommandBuffer()->GetState(); +} + +int32_t PPB_Graphics3D_Impl::CreateTransferBuffer(uint32_t size) { + int32_t id = -1; + GetCommandBuffer()->CreateTransferBuffer(size, &id); + return id; +} + +PP_Bool PPB_Graphics3D_Impl::DestroyTransferBuffer(int32_t id) { + GetCommandBuffer()->DestroyTransferBuffer(id); + return PP_TRUE; +} + +PP_Bool PPB_Graphics3D_Impl::GetTransferBuffer(int32_t id, + int* shm_handle, + uint32_t* shm_size) { + gpu::Buffer buffer = GetCommandBuffer()->GetTransferBuffer(id); + return ShmToHandle(buffer.shared_memory, buffer.size, shm_handle, shm_size); +} + +PP_Bool PPB_Graphics3D_Impl::Flush(int32_t put_offset) { + GetCommandBuffer()->Flush(put_offset); + return PP_TRUE; +} + +gpu::CommandBuffer::State PPB_Graphics3D_Impl::FlushSync(int32_t put_offset) { + gpu::CommandBuffer::State state = GetCommandBuffer()->GetState(); + return GetCommandBuffer()->FlushSync(put_offset, state.get_offset); +} + +gpu::CommandBuffer::State PPB_Graphics3D_Impl::FlushSyncFast( + int32_t put_offset, + int32_t last_known_get) { + return GetCommandBuffer()->FlushSync(put_offset, last_known_get); +} + +uint32_t PPB_Graphics3D_Impl::InsertSyncPoint() { + return GetCommandBuffer()->InsertSyncPoint(); +} + +bool PPB_Graphics3D_Impl::BindToInstance(bool bind) { + bound_to_instance_ = bind; + return true; +} + +bool PPB_Graphics3D_Impl::IsOpaque() { + return platform_context_->IsOpaque(); +} + +void PPB_Graphics3D_Impl::ViewWillInitiatePaint() { +} + +void PPB_Graphics3D_Impl::ViewInitiatedPaint() { + commit_pending_ = false; + + if (HasPendingSwap()) + SwapBuffersACK(PP_OK); +} + +void PPB_Graphics3D_Impl::ViewFlushedPaint() { +} + +gpu::CommandBuffer* PPB_Graphics3D_Impl::GetCommandBuffer() { + return platform_context_->GetCommandBuffer(); +} + +int32 PPB_Graphics3D_Impl::DoSwapBuffers() { + // We do not have a GLES2 implementation when using an OOP proxy. + // The plugin-side proxy is responsible for adding the SwapBuffers command + // to the command buffer in that case. + if (gles2_impl()) + gles2_impl()->SwapBuffers(); + + if (bound_to_instance_) { + // If we are bound to the instance, we need to ask the compositor + // to commit our backing texture so that the graphics appears on the page. + // When the backing texture will be committed we get notified via + // ViewFlushedPaint(). + // + // Don't need to check for NULL from GetPluginInstance since when we're + // bound, we know our instance is valid. + ResourceHelper::GetPluginInstance(this)->CommitBackingTexture(); + commit_pending_ = true; + } else { + // Wait for the command to complete on the GPU to allow for throttling. + platform_context_->Echo(base::Bind(&PPB_Graphics3D_Impl::OnSwapBuffers, + weak_ptr_factory_.GetWeakPtr())); + } + + + return PP_OK_COMPLETIONPENDING; +} + +bool PPB_Graphics3D_Impl::Init(PPB_Graphics3D_API* share_context, + const int32_t* attrib_list) { + if (!InitRaw(share_context, attrib_list)) + return false; + + gpu::CommandBuffer* command_buffer = GetCommandBuffer(); + if (!command_buffer->Initialize()) + return false; + + gpu::gles2::GLES2Implementation* share_gles2 = NULL; + if (share_context) { + share_gles2 = + static_cast<PPB_Graphics3D_Shared*>(share_context)->gles2_impl(); + } + + return CreateGLES2Impl(kCommandBufferSize, kTransferBufferSize, + share_gles2); +} + +bool PPB_Graphics3D_Impl::InitRaw(PPB_Graphics3D_API* share_context, + const int32_t* attrib_list) { + PluginInstanceImpl* plugin_instance = ResourceHelper::GetPluginInstance(this); + if (!plugin_instance) + return false; + + PluginDelegate::PlatformContext3D* share_platform_context = NULL; + if (share_context) { + PPB_Graphics3D_Impl* share_graphics = + static_cast<PPB_Graphics3D_Impl*>(share_context); + share_platform_context = share_graphics->platform_context(); + } + + platform_context_.reset(plugin_instance->CreateContext3D()); + if (!platform_context_) + return false; + + if (!platform_context_->Init(attrib_list, share_platform_context)) + return false; + + platform_context_->SetContextLostCallback( + base::Bind(&PPB_Graphics3D_Impl::OnContextLost, + weak_ptr_factory_.GetWeakPtr())); + + platform_context_->SetOnConsoleMessageCallback( + base::Bind(&PPB_Graphics3D_Impl::OnConsoleMessage, + weak_ptr_factory_.GetWeakPtr())); + return true; +} + +void PPB_Graphics3D_Impl::OnConsoleMessage(const std::string& message, + int id) { + if (!bound_to_instance_) + return; + WebPluginContainer* container = + ResourceHelper::GetPluginInstance(this)->container(); + if (!container) + return; + WebFrame* frame = container->element().document().frame(); + if (!frame) + return; + WebConsoleMessage console_message = WebConsoleMessage( + WebConsoleMessage::LevelError, WebString(UTF8ToUTF16(message))); + frame->addMessageToConsole(console_message); +} + +void PPB_Graphics3D_Impl::OnSwapBuffers() { + if (HasPendingSwap()) { + // If we're off-screen, no need to trigger and wait for compositing. + // Just send the swap-buffers ACK to the plugin immediately. + commit_pending_ = false; + SwapBuffersACK(PP_OK); + } +} + +void PPB_Graphics3D_Impl::OnContextLost() { + // Don't need to check for NULL from GetPluginInstance since when we're + // bound, we know our instance is valid. + if (bound_to_instance_) + ResourceHelper::GetPluginInstance(this)->BindGraphics(pp_instance(), 0); + + // Send context lost to plugin. This may have been caused by a PPAPI call, so + // avoid re-entering. + base::MessageLoop::current()->PostTask( + FROM_HERE, + base::Bind(&PPB_Graphics3D_Impl::SendContextLost, + weak_ptr_factory_.GetWeakPtr())); +} + +void PPB_Graphics3D_Impl::SendContextLost() { + // By the time we run this, the instance may have been deleted, or in the + // process of being deleted. Even in the latter case, we don't want to send a + // callback after DidDestroy. + PluginInstanceImpl* instance = ResourceHelper::GetPluginInstance(this); + if (!instance || !instance->container()) + return; + + // This PPB_Graphics3D_Impl could be deleted during the call to + // GetPluginInterface (which sends a sync message in some cases). We still + // send the Graphics3DContextLost to the plugin; the instance may care about + // that event even though this context has been destroyed. + PP_Instance this_pp_instance = pp_instance(); + const PPP_Graphics3D* ppp_graphics_3d = + static_cast<const PPP_Graphics3D*>( + instance->module()->GetPluginInterface( + PPP_GRAPHICS_3D_INTERFACE)); + if (ppp_graphics_3d) + ppp_graphics_3d->Graphics3DContextLost(this_pp_instance); +} + +} // namespace ppapi +} // namespace webkit |