diff options
author | apatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-24 22:27:04 +0000 |
---|---|---|
committer | apatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-24 22:27:04 +0000 |
commit | 8ceb44c74fc375df749b60acc6fc01b5327c6d18 (patch) | |
tree | 0512ef018e445f45d142e8a79ed4a19b9390b6d3 | |
parent | c16b5958cc9a47992e6c24473258582773036af5 (diff) | |
download | chromium_src-8ceb44c74fc375df749b60acc6fc01b5327c6d18.zip chromium_src-8ceb44c74fc375df749b60acc6fc01b5327c6d18.tar.gz chromium_src-8ceb44c74fc375df749b60acc6fc01b5327c6d18.tar.bz2 |
I just put the code that does not compile on ARM. Trybots will fail because I had to remove these from the CL to make gcl upload properly accept it.
A + base\scoped_open_process.h
A + chrome\plugin\command_buffer_stub_win.cc
TEST=try
BUG=none
Review URL: http://codereview.chromium.org/661022
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@39937 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | base/base.gypi | 1 | ||||
-rw-r--r-- | base/scoped_open_process.h | 49 | ||||
-rwxr-xr-x | chrome/chrome.gyp | 3 | ||||
-rw-r--r-- | chrome/common/command_buffer_messages_internal.h | 4 | ||||
-rw-r--r-- | chrome/plugin/command_buffer_stub.cc | 84 | ||||
-rw-r--r-- | chrome/plugin/command_buffer_stub.h | 11 | ||||
-rw-r--r-- | chrome/plugin/command_buffer_stub_win.cc | 78 | ||||
-rw-r--r-- | chrome/renderer/command_buffer_proxy.cc | 19 | ||||
-rw-r--r-- | chrome/renderer/command_buffer_proxy.h | 9 | ||||
-rw-r--r-- | chrome/renderer/webplugin_delegate_pepper.cc | 44 | ||||
-rw-r--r-- | chrome/renderer/webplugin_delegate_pepper.h | 11 | ||||
-rw-r--r-- | gpu/demos/framework/demo.cc | 4 | ||||
-rw-r--r-- | gpu/demos/framework/demo.h | 4 | ||||
-rw-r--r-- | gpu/demos/framework/main_pepper.cc | 5 | ||||
-rw-r--r-- | gpu/demos/framework/plugin.cc | 35 | ||||
-rw-r--r-- | gpu/demos/framework/plugin.h | 4 | ||||
-rw-r--r-- | gpu/demos/framework/window_win.cc | 4 | ||||
-rw-r--r-- | gpu/demos/gles2_book/simple_vertex_shader.cc | 4 | ||||
-rw-r--r-- | gpu/pgl/pgl.cc | 2 | ||||
-rw-r--r-- | gpu/pgl/pgl.h | 16 | ||||
-rw-r--r-- | third_party/npapi/bindings/npapi_extensions.h | 10 | ||||
-rw-r--r-- | webkit/tools/pepper_test_plugin/plugin_object.cc | 4 |
22 files changed, 335 insertions, 70 deletions
diff --git a/base/base.gypi b/base/base.gypi index aee1361..1d4b3e0 100644 --- a/base/base.gypi +++ b/base/base.gypi @@ -179,6 +179,7 @@ 'scoped_nsautorelease_pool.mm', 'scoped_nsdisable_screen_updates.h', 'scoped_nsobject.h', + 'scoped_open_process.h', 'scoped_ptr.h', 'scoped_temp_dir.cc', 'scoped_temp_dir.h', diff --git a/base/scoped_open_process.h b/base/scoped_open_process.h new file mode 100644 index 0000000..9badc76 --- /dev/null +++ b/base/scoped_open_process.h @@ -0,0 +1,49 @@ +// Copyright (c) 2010 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. + +#ifndef BASE_SCOPED_OPEN_PROCESS_H_ +#define BASE_SCOPED_OPEN_PROCESS_H_ + +#include "base/process.h" +#include "base/process_util.h" + +namespace base { + +// A class that opens a process from its process id and closes it when the +// instance goes out of scope. +class ScopedOpenProcess { + public: + ScopedOpenProcess() : handle_(kNullProcessHandle) { + } + + // Automatically close the process. + ~ScopedOpenProcess() { + Close(); + } + + // Open a new process by pid. Closes any previously opened process (even if + // opening the new one fails). + bool Open(ProcessId pid) { + Close(); + return OpenProcessHandle(pid, &handle_); + } + + // Close the previously opened process. + void Close() { + if (handle_ == kNullProcessHandle) + return; + + CloseProcessHandle(handle_); + handle_ = kNullProcessHandle; + } + + ProcessHandle handle() const { return handle_; } + + private: + ProcessHandle handle_; + DISALLOW_COPY_AND_ASSIGN(ScopedOpenProcess); +}; +} // namespace base + +#endif // BASE_SCOPED_OPEN_PROCESS_H_ diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index 1441086..fa209a7 100755 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -529,7 +529,8 @@ 'sources': [ 'plugin/command_buffer_stub.cc', 'plugin/command_buffer_stub.h', - ], + 'plugin/command_buffer_stub_win.cc', + ], },], ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris"', { 'dependencies': [ diff --git a/chrome/common/command_buffer_messages_internal.h b/chrome/common/command_buffer_messages_internal.h index 6d08dd3..5a62b00 100644 --- a/chrome/common/command_buffer_messages_internal.h +++ b/chrome/common/command_buffer_messages_internal.h @@ -55,6 +55,10 @@ IPC_BEGIN_MESSAGES(CommandBuffer) base::SharedMemoryHandle /* transfer_buffer */, uint32 /* size */) + // Send from command buffer stub to proxy when window is invalid and must be + // repainted. + IPC_MESSAGE_ROUTED0(CommandBufferMsg_NotifyRepaint) + #if defined(OS_MACOSX) // On Mac OS X the GPU plugin must be offscreen, because there is no // true cross-process window hierarchy. For this reason we must send diff --git a/chrome/plugin/command_buffer_stub.cc b/chrome/plugin/command_buffer_stub.cc index 103bde3..d8cc7d4 100644 --- a/chrome/plugin/command_buffer_stub.cc +++ b/chrome/plugin/command_buffer_stub.cc @@ -3,7 +3,7 @@ // found in the LICENSE file. #include "base/callback.h" -#include "base/process_util.h" +#include "base/scoped_open_process.h" #include "base/shared_memory.h" #include "chrome/common/command_buffer_messages.h" #include "chrome/common/plugin_messages.h" @@ -23,6 +23,7 @@ CommandBufferStub::CommandBufferStub(PluginChannel* channel, } CommandBufferStub::~CommandBufferStub() { + Destroy(); channel_->RemoveRoute(route_id_); } @@ -67,38 +68,57 @@ void CommandBufferStub::OnInitialize(int32 size, // Assume service is responsible for duplicating the handle from the calling // process. - base::ProcessHandle peer_handle; - if (!base::OpenProcessHandle(channel_->peer_pid(), &peer_handle)) + base::ScopedOpenProcess peer_process; + if (!peer_process.Open(channel_->peer_pid())) return; command_buffer_.reset(new gpu::CommandBufferService); - // Initialize the CommandBufferService and GPUProcessor. - if (command_buffer_->Initialize(size)) { - Buffer buffer = command_buffer_->GetRingBuffer(); - if (buffer.shared_memory) { - processor_ = new gpu::GPUProcessor(command_buffer_.get()); - if (processor_->Initialize(window_)) { - command_buffer_->SetPutOffsetChangeCallback( - NewCallback(processor_.get(), - &gpu::GPUProcessor::ProcessCommands)); + // Initialize the CommandBufferService. + if (!command_buffer_->Initialize(size)) { + Destroy(); + return; + } + + // Get the ring buffer. + Buffer buffer = command_buffer_->GetRingBuffer(); + if (!buffer.shared_memory) { + Destroy(); + return; + } + + // Initialize the GPUProcessor. + processor_ = new gpu::GPUProcessor(command_buffer_.get()); + if (!processor_->Initialize(window_)) { + Destroy(); + return; + } + + // Perform platform specific initialization. + if (!InitializePlatformSpecific()) { + Destroy(); + return; + } + + // Share the ring buffer to the client process. + if (!buffer.shared_memory->ShareToProcess(peer_process.handle(), + ring_buffer)) { + Destroy(); + return; + } + + // Setup callbacks for events. + command_buffer_->SetPutOffsetChangeCallback( + NewCallback(processor_.get(), + &gpu::GPUProcessor::ProcessCommands)); #if defined(OS_MACOSX) - processor_->SetSwapBuffersCallback( - NewCallback(this, - &CommandBufferStub::SwapBuffersCallback)); + processor_->SetSwapBuffersCallback( + NewCallback(this, + &CommandBufferStub::SwapBuffersCallback)); processor_->SetTransportDIBAllocAndFree( NewCallback(this, &CommandBufferStub::AllocTransportDIB), NewCallback(this, &CommandBufferStub::FreeTransportDIB)); #endif - buffer.shared_memory->ShareToProcess(peer_handle, ring_buffer); - } else { - processor_ = NULL; - command_buffer_.reset(); - } - } - } - - base::CloseProcessHandle(peer_handle); } void CommandBufferStub::OnGetState(gpu::CommandBuffer::State* state) { @@ -150,6 +170,22 @@ void CommandBufferStub::OnGetTransferBuffer( base::CloseProcessHandle(peer_handle); } +void CommandBufferStub::Destroy() { + processor_ = NULL; + command_buffer_.reset(); + + DestroyPlatformSpecific(); +} + +#if !defined(OS_WIN) +bool CommandBufferStub::InitializePlatformSpecific() { + return true; +} + +void CommandBufferStub::DestroyPlatformSpecific() { +} +#endif // defined(OS_WIN) + #if defined(OS_MACOSX) void CommandBufferStub::OnSetWindowSize(int32 width, int32 height) { // Try using the IOSurface version first. diff --git a/chrome/plugin/command_buffer_stub.h b/chrome/plugin/command_buffer_stub.h index 219aadb..0b0a556 100644 --- a/chrome/plugin/command_buffer_stub.h +++ b/chrome/plugin/command_buffer_stub.h @@ -38,6 +38,10 @@ class CommandBufferStub : public IPC::Channel::Listener, int route_id() const { return route_id_; } + // Notify the client that it must repaint due to the window becoming invalid + // or a lost context. + void NotifyRepaint(); + private: // Message handlers: void OnInitialize(int32 size, base::SharedMemoryHandle* ring_buffer); @@ -50,6 +54,13 @@ class CommandBufferStub : public IPC::Channel::Listener, void OnGetTransferBuffer(int32 id, base::SharedMemoryHandle* transfer_buffer, uint32* size); + + // Destroy all owned objects. + void Destroy(); + + bool InitializePlatformSpecific(); + void DestroyPlatformSpecific(); + #if defined(OS_MACOSX) void OnSetWindowSize(int32 width, int32 height); void SwapBuffersCallback(); diff --git a/chrome/plugin/command_buffer_stub_win.cc b/chrome/plugin/command_buffer_stub_win.cc new file mode 100644 index 0000000..656bbd1 --- /dev/null +++ b/chrome/plugin/command_buffer_stub_win.cc @@ -0,0 +1,78 @@ +// Copyright (c) 2010 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 <windows.h> + +#include "chrome/common/command_buffer_messages.h" +#include "chrome/plugin/command_buffer_stub.h" + +namespace { +const wchar_t* kPreviousWndProcProperty = L"CommandBufferStubPrevWndProc"; +const wchar_t* kCommandBufferStubProperty = L"CommandBufferStub"; + +// Message handler for the GPU plugin's child window. Used to intercept +// WM_PAINT events and forward repaint notifications to the client. +LRESULT WINAPI WndProc(HWND handle, + UINT message, + WPARAM w_param, + LPARAM l_param) { + WNDPROC previous_wnd_proc = reinterpret_cast<WNDPROC>( + ::GetProp(handle, kPreviousWndProcProperty)); + CommandBufferStub* stub = reinterpret_cast<CommandBufferStub*>( + ::GetProp(handle, kCommandBufferStubProperty)); + + switch (message) { + case WM_ERASEBKGND: + // Do not clear background. Avoids flickering. + return 1; + case WM_PAINT: + // Validate the whole window to prevent another WM_PAINT message. + ValidateRect(handle, NULL); + + // Notify client that the window is invalid and needs to be repainted. + stub->NotifyRepaint(); + + return 1; + default: + return CallWindowProc(previous_wnd_proc, + handle, + message, + w_param, + l_param); + } +} +} // namespace anonymous + +void CommandBufferStub::NotifyRepaint() { + Send(new CommandBufferMsg_NotifyRepaint(route_id_)); +} + +bool CommandBufferStub::InitializePlatformSpecific() { + // Subclass window. + WNDPROC previous_wnd_proc = reinterpret_cast<WNDPROC>( + ::GetWindowLongPtr(window_, GWLP_WNDPROC)); + ::SetProp(window_, + kPreviousWndProcProperty, + reinterpret_cast<HANDLE>(previous_wnd_proc)); + ::SetWindowLongPtr(window_, + GWLP_WNDPROC, + reinterpret_cast<LONG_PTR>(WndProc)); + + // Record pointer to this in window. + ::SetProp(window_, + kCommandBufferStubProperty, + reinterpret_cast<HANDLE>(this)); + + return true; +} + +void CommandBufferStub::DestroyPlatformSpecific() { + // Restore window. + WNDPROC previous_wnd_proc = reinterpret_cast<WNDPROC>( + ::GetProp(window_, kPreviousWndProcProperty)); + ::SetWindowLongPtr(window_, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>( + previous_wnd_proc)); + ::RemoveProp(window_, kPreviousWndProcProperty); + ::RemoveProp(window_, kCommandBufferStubProperty); +} diff --git a/chrome/renderer/command_buffer_proxy.cc b/chrome/renderer/command_buffer_proxy.cc index 2b71fa8..b2eaa86 100644 --- a/chrome/renderer/command_buffer_proxy.cc +++ b/chrome/renderer/command_buffer_proxy.cc @@ -37,6 +37,8 @@ CommandBufferProxy::~CommandBufferProxy() { void CommandBufferProxy::OnMessageReceived(const IPC::Message& message) { IPC_BEGIN_MESSAGE_MAP(CommandBufferProxy, message) IPC_MESSAGE_HANDLER(CommandBufferMsg_UpdateState, OnUpdateState); + IPC_MESSAGE_HANDLER(CommandBufferMsg_NotifyRepaint, + OnNotifyRepaint); IPC_MESSAGE_UNHANDLED_ERROR() IPC_END_MESSAGE_MAP() } @@ -142,16 +144,7 @@ Buffer CommandBufferProxy::GetTransferBuffer(int32 id) { } // Cache the transfer buffer shared memory object client side. -#if defined(OS_WIN) - // TODO(piman): Does Windows needs this version of the constructor ? It - // duplicates the handle, but I'm not sure why it is necessary - it was - // already duped by the CommandBufferStub. - base::SharedMemory* shared_memory = - new base::SharedMemory(handle, false, base::GetCurrentProcessHandle()); -#else - base::SharedMemory* shared_memory = - new base::SharedMemory(handle, false); -#endif + base::SharedMemory* shared_memory = new base::SharedMemory(handle, false); // Map the shared memory on demand. if (!shared_memory->memory()) { @@ -175,6 +168,12 @@ void CommandBufferProxy::SetToken(int32 token) { NOTREACHED(); } +void CommandBufferProxy::OnNotifyRepaint() { + if (notify_repaint_task_.get()) + MessageLoop::current()->PostNonNestableTask( + FROM_HERE, notify_repaint_task_.release()); +} + void CommandBufferProxy::SetParseError( gpu::error::Error error) { // Not implemented in proxy. diff --git a/chrome/renderer/command_buffer_proxy.h b/chrome/renderer/command_buffer_proxy.h index a2fb9c4..990f6f3 100644 --- a/chrome/renderer/command_buffer_proxy.h +++ b/chrome/renderer/command_buffer_proxy.h @@ -51,6 +51,12 @@ class CommandBufferProxy : public gpu::CommandBuffer, virtual void SetToken(int32 token); virtual void SetParseError(gpu::error::Error error); + // Set a task that will be invoked the next time the window becomes invalid + // and needs to be repainted. Takes ownership of task. + void SetNotifyRepaintTask(Task* task) { + notify_repaint_task_.reset(task); + } + #if defined(OS_MACOSX) virtual void SetWindowSize(int32 width, int32 height); #endif @@ -71,6 +77,7 @@ class CommandBufferProxy : public gpu::CommandBuffer, private: // Message handlers: void OnUpdateState(gpu::CommandBuffer::State state); + void OnNotifyRepaint(); // As with the service, the client takes ownership of the ring buffer. int32 size_; @@ -90,6 +97,8 @@ class CommandBufferProxy : public gpu::CommandBuffer, typedef std::queue<linked_ptr<Task> > AsyncFlushTaskQueue; AsyncFlushTaskQueue pending_async_flush_tasks_; + scoped_ptr<Task> notify_repaint_task_; + DISALLOW_COPY_AND_ASSIGN(CommandBufferProxy); }; diff --git a/chrome/renderer/webplugin_delegate_pepper.cc b/chrome/renderer/webplugin_delegate_pepper.cc index ad8a952..10c66cd 100644 --- a/chrome/renderer/webplugin_delegate_pepper.cc +++ b/chrome/renderer/webplugin_delegate_pepper.cc @@ -168,17 +168,7 @@ void WebPluginDelegatePepper::UpdateGeometry( if (!instance()) return; - // TODO(sehr): do we need all this? - window_.clipRect.top = clip_rect_.y(); - window_.clipRect.left = clip_rect_.x(); - window_.clipRect.bottom = clip_rect_.y() + clip_rect_.height(); - window_.clipRect.right = clip_rect_.x() + clip_rect_.width(); - window_.height = window_rect_.height(); - window_.width = window_rect_.width(); - window_.x = window_rect_.x(); - window_.y = window_rect_.y(); - window_.type = NPWindowTypeDrawable; - instance()->NPP_SetWindow(&window_); + ForwardSetWindow(); } NPObject* WebPluginDelegatePepper::GetPluginScriptableObject() { @@ -373,8 +363,11 @@ NPError WebPluginDelegatePepper::Device3DInitializeContext( Buffer ring_buffer = command_buffer_->GetRingBuffer(); context->commandBuffer = ring_buffer.ptr; context->commandBufferSize = state.size; + context->repaintCallback = NULL; Synchronize3DContext(context, state); + ScheduleHandleRepaint(instance_->npp(), context); + // Ensure the service knows the window size before rendering anything. nested_delegate_->UpdateGeometry(window_rect_, clip_rect_); #if defined(OS_MACOSX) @@ -646,6 +639,19 @@ WebPluginDelegatePepper::~WebPluginDelegatePepper() { DestroyInstance(); } +void WebPluginDelegatePepper::ForwardSetWindow() { + window_.clipRect.top = clip_rect_.y(); + window_.clipRect.left = clip_rect_.x(); + window_.clipRect.bottom = clip_rect_.y() + clip_rect_.height(); + window_.clipRect.right = clip_rect_.x() + clip_rect_.width(); + window_.height = window_rect_.height(); + window_.width = window_rect_.width(); + window_.x = window_rect_.x(); + window_.y = window_rect_.y(); + window_.type = NPWindowTypeDrawable; + instance()->NPP_SetWindow(&window_); +} + void WebPluginDelegatePepper::PluginDestroyed() { delete this; } @@ -799,6 +805,21 @@ bool WebPluginDelegatePepper::HandleInputEvent(const WebInputEvent& event, } #if defined(ENABLE_GPU) + +void WebPluginDelegatePepper::ScheduleHandleRepaint( + NPP npp, NPDeviceContext3D* context) { + command_buffer_->SetNotifyRepaintTask(method_factory3d_.NewRunnableMethod( + &WebPluginDelegatePepper::ForwardHandleRepaint, + npp, + context)); +} + +void WebPluginDelegatePepper::ForwardHandleRepaint( + NPP npp, NPDeviceContext3D* context) { + context->repaintCallback(npp, context); + ScheduleHandleRepaint(npp, context); +} + void WebPluginDelegatePepper::Synchronize3DContext( NPDeviceContext3D* context, gpu::CommandBuffer::State state) { @@ -819,6 +840,7 @@ void WebPluginDelegatePepper::Device3DUpdateState( callback(npp, context, NPERR_NO_ERROR, user_data); } } + #endif // ENABLE_GPU void WebPluginDelegatePepper::SendNestedDelegateGeometryToBrowser( diff --git a/chrome/renderer/webplugin_delegate_pepper.h b/chrome/renderer/webplugin_delegate_pepper.h index 5082d64..a67b530 100644 --- a/chrome/renderer/webplugin_delegate_pepper.h +++ b/chrome/renderer/webplugin_delegate_pepper.h @@ -150,9 +150,9 @@ class WebPluginDelegatePepper : public webkit_glue::WebPluginDelegate { NPAPI::PluginInstance *instance); ~WebPluginDelegatePepper(); - // Tells the plugin about the current state of the window. - // See NPAPI NPP_SetWindow for more information. - void WindowlessSetWindow(bool force_set_window); + // Set a task that calls the repaint callback the next time the window + // is invalid and needs to be repainted. + void ScheduleHandleRepaint(NPP npp, NPDeviceContext3D* context); //----------------------------------------- // used for windowed and windowless plugins @@ -162,7 +162,12 @@ class WebPluginDelegatePepper : public webkit_glue::WebPluginDelegate { // Closes down and destroys our plugin instance. void DestroyInstance(); + void ForwardSetWindow(); + #if defined(ENABLE_GPU) + + void ForwardHandleRepaint(NPP npp, NPDeviceContext3D* context); + // Synchronize a 3D context state with the service. void Synchronize3DContext(NPDeviceContext3D* context, gpu::CommandBuffer::State state); diff --git a/gpu/demos/framework/demo.cc b/gpu/demos/framework/demo.cc index 49fa519..1679b3f 100644 --- a/gpu/demos/framework/demo.cc +++ b/gpu/demos/framework/demo.cc @@ -31,5 +31,9 @@ void Demo::Draw() { Render(elapsed_sec); } +bool Demo::IsAnimated() { + return false; +} + } // namespace demos } // namespace gpu diff --git a/gpu/demos/framework/demo.h b/gpu/demos/framework/demo.h index 801609b..28c8923 100644 --- a/gpu/demos/framework/demo.h +++ b/gpu/demos/framework/demo.h @@ -33,6 +33,10 @@ class Demo { // a rendering context has already been created and made current. virtual bool InitGL() = 0; + // Returns whether the demo is animated. Animated demos are drawn + // continuously. Unanimated demos are only drawn when the window is invalid. + virtual bool IsAnimated(); + // This function is called by the framework to perform OpenGL rendering. // When this function is called, it is assumed that the rendering context // has been made current. diff --git a/gpu/demos/framework/main_pepper.cc b/gpu/demos/framework/main_pepper.cc index 6937b62..cf8f510 100644 --- a/gpu/demos/framework/main_pepper.cc +++ b/gpu/demos/framework/main_pepper.cc @@ -90,6 +90,11 @@ void NPP_Print(NPP instance, NPPrint* platformPrint) { } int16 NPP_HandleEvent(NPP instance, void* event) { + Plugin* plugin = static_cast<Plugin*>(instance->pdata); + + if (plugin) + return plugin->HandleEvent(*static_cast<NPPepperEvent*>(event)); + return 0; } diff --git a/gpu/demos/framework/plugin.cc b/gpu/demos/framework/plugin.cc index 0514f81..9ba01d4 100644 --- a/gpu/demos/framework/plugin.cc +++ b/gpu/demos/framework/plugin.cc @@ -74,8 +74,13 @@ NPClass plugin_class = { PluginSetProperty, }; -void PaintCallback(void* data) { - reinterpret_cast<gpu::demos::Plugin*>(data)->Paint(); +void TickCallback(void* data) { + reinterpret_cast<gpu::demos::Plugin*>(data)->Tick(); +} + +void RepaintCallback(NPP npp, NPDeviceContext3D* /* context */) { + Plugin* plugin = static_cast<Plugin*>(npp->pdata); + plugin->Paint(); } } @@ -96,7 +101,7 @@ Plugin::~Plugin() { // Destroy demo while GL context is current and before it is destroyed. pglMakeCurrent(pgl_context_); demo_.reset(); - pglMakeCurrent(NULL); + pglMakeCurrent(PGL_NO_CONTEXT); DestroyContext(); } @@ -121,10 +126,22 @@ void Plugin::SetWindow(const NPWindow& window) { if (!pgl_context_) { CreateContext(); + + // Schedule first call to Tick. + if (demo_->IsAnimated()) + g_browser->pluginthreadasynccall(npp_, TickCallback, this); } +} - // Schedule the first call to Draw. - g_browser->pluginthreadasynccall(npp_, PaintCallback, this); +int32 Plugin::HandleEvent(const NPPepperEvent& event) { + return 0; +} + +void Plugin::Tick() { + Paint(); + + // Schedule another call to Tick. + g_browser->pluginthreadasynccall(npp_, TickCallback, this); } void Plugin::Paint() { @@ -136,10 +153,7 @@ void Plugin::Paint() { demo_->Draw(); pglSwapBuffers(); - pglMakeCurrent(NULL); - - // Schedule another call to Paint. - g_browser->pluginthreadasynccall(npp_, PaintCallback, this); + pglMakeCurrent(PGL_NO_CONTEXT); } void Plugin::CreateContext() { @@ -149,6 +163,7 @@ void Plugin::CreateContext() { NPDeviceContext3DConfig config; config.commandBufferSize = kCommandBufferSize; device3d_->initializeContext(npp_, &config, &context3d_); + context3d_.repaintCallback = RepaintCallback; // Create a PGL context. pgl_context_ = pglCreateContext(npp_, device3d_, &context3d_); @@ -156,7 +171,7 @@ void Plugin::CreateContext() { // Initialize demo. pglMakeCurrent(pgl_context_); CHECK(demo_->InitGL()); - pglMakeCurrent(NULL); + pglMakeCurrent(PGL_NO_CONTEXT); } void Plugin::DestroyContext() { diff --git a/gpu/demos/framework/plugin.h b/gpu/demos/framework/plugin.h index 0f4b55e..640d9c0 100644 --- a/gpu/demos/framework/plugin.h +++ b/gpu/demos/framework/plugin.h @@ -26,6 +26,10 @@ class Plugin : public NPObject { NPP npp() const { return npp_; } void New(NPMIMEType pluginType, int16 argc, char* argn[], char* argv[]); void SetWindow(const NPWindow& window); + int32 HandleEvent(const NPPepperEvent& event); + + // Called continuously for animated demos. + void Tick(); // Called by the browser to paint the window. void Paint(); diff --git a/gpu/demos/framework/window_win.cc b/gpu/demos/framework/window_win.cc index 37f41c2..dfd79fc 100644 --- a/gpu/demos/framework/window_win.cc +++ b/gpu/demos/framework/window_win.cc @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "gpu/demos/framework/demo.h" #include "gpu/demos/framework/window.h" namespace { @@ -52,7 +53,8 @@ void Window::MainLoop() { ::DispatchMessage(&msg); } // Message queue is empty and application has not quit yet - keep painting. - if (!done) ::InvalidateRect(window_handle_, NULL, FALSE); + if (!done && demo_->IsAnimated()) + ::InvalidateRect(window_handle_,NULL, FALSE); } } diff --git a/gpu/demos/gles2_book/simple_vertex_shader.cc b/gpu/demos/gles2_book/simple_vertex_shader.cc index dff99ca..0f8b72e 100644 --- a/gpu/demos/gles2_book/simple_vertex_shader.cc +++ b/gpu/demos/gles2_book/simple_vertex_shader.cc @@ -22,6 +22,10 @@ class SimpleVertexShader : public Example<SVSUserData> { const wchar_t* Title() const { return L"Simple Vertex Shader"; } + + virtual bool IsAnimated() { + return true; + } }; } // namespace gles2_book diff --git a/gpu/pgl/pgl.cc b/gpu/pgl/pgl.cc index d357fe2..59c2635 100644 --- a/gpu/pgl/pgl.cc +++ b/gpu/pgl/pgl.cc @@ -223,7 +223,7 @@ PGLBoolean pglDestroyContext(PGLContext pgl_context) { return PGL_FALSE; if (pgl_context == pglGetCurrentContext()) - pglMakeCurrent(NULL); + pglMakeCurrent(PGL_NO_CONTEXT); delete static_cast<PGLContextImpl*>(pgl_context); return PGL_TRUE; diff --git a/gpu/pgl/pgl.h b/gpu/pgl/pgl.h index ac67ec1..118d6fe 100644 --- a/gpu/pgl/pgl.h +++ b/gpu/pgl/pgl.h @@ -8,8 +8,10 @@ #include "npapi.h" #include "npapi_extensions.h" -#define PGL_TRUE 1 -#define PGL_FALSE 0 +#define PGL_TRUE 1 +#define PGL_FALSE 0 + +#define PGL_NO_CONTEXT ((PGLContext) 0) #ifdef __cplusplus extern "C" { @@ -21,11 +23,11 @@ typedef int32 PGLInt; // These are the same error codes as used by EGL. enum { - PGL_SUCCESS = 0x3000, - PGL_NOT_INITIALIZED = 0x3001, - PGL_BAD_CONTEXT = 0x3006, - PGL_BAD_PARAMETER = 0x300C, - PGL_CONTEXT_LOST = 0x300E + PGL_SUCCESS = 0x3000, + PGL_NOT_INITIALIZED = 0x3001, + PGL_BAD_CONTEXT = 0x3006, + PGL_BAD_PARAMETER = 0x300C, + PGL_CONTEXT_LOST = 0x300E }; // Initialize the PGL library. This must have completed before any other PGL diff --git a/third_party/npapi/bindings/npapi_extensions.h b/third_party/npapi/bindings/npapi_extensions.h index fca509e..011628e 100644 --- a/third_party/npapi/bindings/npapi_extensions.h +++ b/third_party/npapi/bindings/npapi_extensions.h @@ -295,6 +295,11 @@ typedef enum _NPDeviceContext3DError { NPDeviceContext3DError_GenericError } NPDeviceContext3DError; +typedef struct _NPDeviceContext3D NPDeviceContext3D; + +typedef void (*NPDeviceContext3DRepaintPtr)(NPP npp, + NPDeviceContext3D* context); + typedef struct _NPDeviceContext3D { void* reserved; @@ -322,6 +327,11 @@ typedef struct _NPDeviceContext3D // Last processed token. Synchronized on flush. int32 token; + // Callback invoked on the main thread when the context must be repainted. + // TODO(apatrick): move this out of the context struct like the rest of the + // fields. + NPDeviceContext3DRepaintPtr repaintCallback; + // Error status. Synchronized on flush. NPDeviceContext3DError error; } NPDeviceContext3D; diff --git a/webkit/tools/pepper_test_plugin/plugin_object.cc b/webkit/tools/pepper_test_plugin/plugin_object.cc index 35c2a2c..6e755ef 100644 --- a/webkit/tools/pepper_test_plugin/plugin_object.cc +++ b/webkit/tools/pepper_test_plugin/plugin_object.cc @@ -422,7 +422,7 @@ void PluginObject::Initialize3D() { // Initialize the demo GL state. pglMakeCurrent(pgl_context_); GLFromCPPInit(); - pglMakeCurrent(NULL); + pglMakeCurrent(PGL_NO_CONTEXT); #endif // INDEPENDENT_PLUGIN } @@ -458,7 +458,7 @@ void PluginObject::Draw3D() { glViewport(0, 0, width_, height_); GLFromCPPDraw(); pglSwapBuffers(); - pglMakeCurrent(NULL); + pglMakeCurrent(PGL_NO_CONTEXT); // Async flushes just to see them working. context3d_.waitForProgress = true; |