diff options
Diffstat (limited to 'chrome/plugin')
-rw-r--r-- | chrome/plugin/webplugin_delegate_stub.cc | 14 | ||||
-rw-r--r-- | chrome/plugin/webplugin_delegate_stub.h | 7 | ||||
-rw-r--r-- | chrome/plugin/webplugin_proxy.cc | 115 | ||||
-rw-r--r-- | chrome/plugin/webplugin_proxy.h | 41 |
4 files changed, 113 insertions, 64 deletions
diff --git a/chrome/plugin/webplugin_delegate_stub.cc b/chrome/plugin/webplugin_delegate_stub.cc index e2129f2..84bc069 100644 --- a/chrome/plugin/webplugin_delegate_stub.cc +++ b/chrome/plugin/webplugin_delegate_stub.cc @@ -80,6 +80,8 @@ void WebPluginDelegateStub::OnMessageReceived(const IPC::Message& msg) { OnDidFinishLoadWithReason) IPC_MESSAGE_HANDLER(PluginMsg_SetFocus, OnSetFocus) IPC_MESSAGE_HANDLER(PluginMsg_HandleEvent, OnHandleEvent) + IPC_MESSAGE_HANDLER(PluginMsg_Paint, OnPaint) + IPC_MESSAGE_HANDLER(PluginMsg_DidPaint, OnDidPaint) IPC_MESSAGE_HANDLER(PluginMsg_Print, OnPrint) IPC_MESSAGE_HANDLER(PluginMsg_GetPluginScriptableObject, OnGetPluginScriptableObject) @@ -199,6 +201,14 @@ void WebPluginDelegateStub::OnHandleEvent(const NPEvent& event, *handled = delegate_->HandleEvent(const_cast<NPEvent*>(&event), cursor); } +void WebPluginDelegateStub::OnPaint(const gfx::Rect& damaged_rect) { + webplugin_->Paint(damaged_rect); +} + +void WebPluginDelegateStub::OnDidPaint() { + webplugin_->DidPaint(); +} + void WebPluginDelegateStub::OnPrint(PluginMsg_PrintResponse_Params* params) { gfx::Emf emf; if (!emf.CreateDc(NULL, NULL)) { @@ -229,9 +239,9 @@ void WebPluginDelegateStub::OnUpdateGeometry( const gfx::Rect& clip_rect, bool visible, const SharedMemoryHandle& windowless_buffer, - const SharedMemoryLock& lock) { + const SharedMemoryHandle& background_buffer) { webplugin_->UpdateGeometry( - window_rect, clip_rect, visible, windowless_buffer, lock); + window_rect, clip_rect, visible, windowless_buffer, background_buffer); } void WebPluginDelegateStub::OnGetPluginScriptableObject(int* route_id, diff --git a/chrome/plugin/webplugin_delegate_stub.h b/chrome/plugin/webplugin_delegate_stub.h index cb242b4..78684bf 100644 --- a/chrome/plugin/webplugin_delegate_stub.h +++ b/chrome/plugin/webplugin_delegate_stub.h @@ -57,11 +57,16 @@ class WebPluginDelegateStub : public IPC::Channel::Listener, void OnSetFocus(); void OnHandleEvent(const NPEvent& event, bool* handled, WebCursor* cursor); + + void OnPaint(const gfx::Rect& damaged_rect); + void OnDidPaint(); + void OnPrint(PluginMsg_PrintResponse_Params* params); + void OnUpdateGeometry(const gfx::Rect& window_rect, const gfx::Rect& clip_rect, bool visible, const SharedMemoryHandle& windowless_buffer, - const SharedMemoryLock& lock); + const SharedMemoryHandle& background_buffer); void OnGetPluginScriptableObject(int* route_id, void** npobject_ptr); void OnSendJavaScriptStream(const std::string& url, const std::wstring& result, diff --git a/chrome/plugin/webplugin_proxy.cc b/chrome/plugin/webplugin_proxy.cc index cc091a2..2abafb0 100644 --- a/chrome/plugin/webplugin_proxy.cc +++ b/chrome/plugin/webplugin_proxy.cc @@ -18,9 +18,6 @@ #include "chrome/plugin/npobject_util.h" #include "webkit/glue/plugins/webplugin_delegate_impl.h" -// How many times per second we draw windowless plugins. -static const int kWindowlessPaintFPS = 30; - typedef std::map<CPBrowsingContext, WebPluginProxy*> ContextMap; static ContextMap& GetContextMap() { return *Singleton<ContextMap>::get(); @@ -36,7 +33,8 @@ WebPluginProxy::WebPluginProxy( cp_browsing_context_(0), window_npobject_(NULL), plugin_element_(NULL), - delegate_(delegate) { + delegate_(delegate), + waiting_for_paint_(false) { HANDLE event; BOOL result = DuplicateHandle(channel->renderer_handle(), @@ -81,14 +79,25 @@ void WebPluginProxy::CancelResource(int id) { } void WebPluginProxy::Invalidate() { - Send(new PluginHostMsg_Invalidate(route_id_)); + gfx::Rect rect(0, 0, delegate_->rect().width(), delegate_->rect().height()); + InvalidateRect(rect); } void WebPluginProxy::InvalidateRect(const gfx::Rect& rect) { + // Ignore NPN_InvalidateRect calls with empty rects. + if (rect.IsEmpty()) + return; + damaged_rect_ = damaged_rect_.Union(rect); - if (!paint_timer_.IsRunning()) { - paint_timer_.Start(TimeDelta::FromMilliseconds(1000 / kWindowlessPaintFPS), - this, &WebPluginProxy::OnPaintTimerFired); + // Only send a single InvalidateRect message at a time. From DidPaint we + // will dispatch an additional InvalidateRect message if necessary. + if (!waiting_for_paint_) { + waiting_for_paint_ = true; + // Paint to the plugin bitmap and let the renderer know so it can update + // its backing store. + Paint(damaged_rect_); + Send(new PluginHostMsg_InvalidateRect(route_id_, damaged_rect_)); + damaged_rect_ = gfx::Rect(); } } @@ -190,6 +199,14 @@ WebPluginResourceClient* WebPluginProxy::GetResourceClient(int id) { return iterator->second; } +void WebPluginProxy::DidPaint() { + // If we have an accumulated damaged rect, then check to see if we need to + // send out another InvalidateRect message. + waiting_for_paint_ = false; + if (!damaged_rect_.IsEmpty()) + InvalidateRect(damaged_rect_); +} + void WebPluginProxy::OnResourceCreated(int resource_id, HANDLE cookie) { WebPluginResourceClient* resource_client = reinterpret_cast<WebPluginResourceClient*>(cookie); @@ -233,33 +250,26 @@ void WebPluginProxy::HandleURLRequest(const char *method, Send(new PluginHostMsg_URLRequest(route_id_, params)); } -void WebPluginProxy::OnPaintTimerFired() { +void WebPluginProxy::Paint(const gfx::Rect& rect) { if (!windowless_hdc_) return; - if (damaged_rect_.IsEmpty()) { - paint_timer_.Stop(); - return; - } - - DWORD wait_result = WaitForSingleObject(windowless_buffer_lock_, INFINITE); - DCHECK(wait_result == WAIT_OBJECT_0); - // Clear the damaged area so that if the plugin doesn't paint there we won't // end up with the old values. - gfx::Rect offset_rect = damaged_rect_; - offset_rect.Offset(delegate_->rect().x(), delegate_->rect().y()); - FillRect(windowless_hdc_, &offset_rect.ToRECT(), - static_cast<HBRUSH>(GetStockObject(BLACK_BRUSH))); + gfx::Rect offset_rect = rect; + offset_rect.Offset(delegate_->rect().x(), delegate_->rect().y()); + if (!background_hdc_) { + FillRect(windowless_hdc_, &offset_rect.ToRECT(), + static_cast<HBRUSH>(GetStockObject(BLACK_BRUSH))); + } else { + BitBlt(windowless_hdc_, offset_rect.x(), offset_rect.y(), + offset_rect.width(), offset_rect.height(), background_hdc_, + rect.x(), rect.y(), SRCCOPY); + } // Before we send the invalidate, paint so that renderer uses the updated // bitmap. - delegate_->Paint(windowless_hdc_, damaged_rect_); - BOOL result = ReleaseMutex(windowless_buffer_lock_); - DCHECK(result); - - Send(new PluginHostMsg_InvalidateRect(route_id_, damaged_rect_)); - damaged_rect_ = gfx::Rect(); + delegate_->Paint(windowless_hdc_, offset_rect); } void WebPluginProxy::UpdateGeometry( @@ -267,33 +277,45 @@ void WebPluginProxy::UpdateGeometry( const gfx::Rect& clip_rect, bool visible, const SharedMemoryHandle& windowless_buffer, - const SharedMemoryLock& lock) { + const SharedMemoryHandle& background_buffer) { + gfx::Rect old = delegate_->rect(); bool moved = delegate_->rect().x() != window_rect.x() || delegate_->rect().y() != window_rect.y(); delegate_->UpdateGeometry(window_rect, clip_rect, visible); if (windowless_buffer) { // The plugin's rect changed, so now we have a new buffer to draw into. - SetWindowlessBuffer(windowless_buffer, lock); + SetWindowlessBuffer(windowless_buffer, background_buffer); } else if (moved) { // The plugin moved, so update our world transform. UpdateTransform(); } } -void WebPluginProxy::SetWindowlessBuffer(const SharedMemoryHandle& handle, - const SharedMemoryLock& lock) { +void WebPluginProxy::SetWindowlessBuffer( + const SharedMemoryHandle& windowless_buffer, + const SharedMemoryHandle& background_buffer) { // Convert the shared memory handle to a handle that works in our process, // and then use that to create an HDC. - windowless_shared_section_.Set(win_util::GetSectionFromProcess( - handle, channel_->renderer_handle(), false)); - if (!windowless_buffer_lock_) { - HANDLE dup_handle = NULL; - DuplicateHandle(channel_->renderer_handle(), lock, GetCurrentProcess(), - &dup_handle, 0, FALSE, DUPLICATE_SAME_ACCESS); - windowless_buffer_lock_.Set(dup_handle); + ConvertBuffer(windowless_buffer, + &windowless_shared_section_, + &windowless_bitmap_, + &windowless_hdc_); + if (background_buffer) { + ConvertBuffer(background_buffer, + &background_shared_section_, + &background_bitmap_, + &background_hdc_); } + UpdateTransform(); +} - if (windowless_shared_section_ == NULL || windowless_buffer_lock_ == NULL) { +void WebPluginProxy::ConvertBuffer(const SharedMemoryHandle& buffer, + ScopedHandle* shared_section, + ScopedBitmap* bitmap, + ScopedHDC* hdc) { + shared_section->Set(win_util::GetSectionFromProcess( + buffer, channel_->renderer_handle(), false)); + if (shared_section->Get() == NULL) { NOTREACHED(); return; } @@ -304,24 +326,23 @@ void WebPluginProxy::SetWindowlessBuffer(const SharedMemoryHandle& handle, gfx::CreateBitmapHeader(delegate_->rect().width(), delegate_->rect().height(), &bitmap_header); - windowless_bitmap_.Set(CreateDIBSection( + bitmap->Set(CreateDIBSection( screen_dc, reinterpret_cast<const BITMAPINFO*>(&bitmap_header), - DIB_RGB_COLORS, &data, windowless_shared_section_, 0)); + DIB_RGB_COLORS, &data, shared_section->Get(), 0)); ReleaseDC(NULL, screen_dc); - if (windowless_bitmap_ == NULL) { + if (bitmap->Get() == NULL) { NOTREACHED(); return; } - windowless_hdc_.Set(CreateCompatibleDC(NULL)); - if (windowless_hdc_ == NULL) { + hdc->Set(CreateCompatibleDC(NULL)); + if (hdc->Get() == NULL) { NOTREACHED(); return; } - gfx::PlatformDeviceWin::InitializeDC(windowless_hdc_); - SelectObject(windowless_hdc_, windowless_bitmap_); - UpdateTransform(); + gfx::PlatformDeviceWin::InitializeDC(hdc->Get()); + SelectObject(hdc->Get(), bitmap->Get()); } void WebPluginProxy::UpdateTransform() { diff --git a/chrome/plugin/webplugin_proxy.h b/chrome/plugin/webplugin_proxy.h index 9e1a051..ab50933 100644 --- a/chrome/plugin/webplugin_proxy.h +++ b/chrome/plugin/webplugin_proxy.h @@ -62,6 +62,12 @@ class WebPluginProxy : public WebPlugin { // object with that id exists. WebPluginResourceClient* GetResourceClient(int id); + // For windowless plugins, paints the given rectangle into the local buffer. + void Paint(const gfx::Rect& rect); + + // Callback from the renderer to let us know that a paint occurred. + void DidPaint(); + // Notification received on a plugin issued resource request // creation. void OnResourceCreated(int resource_id, HANDLE cookie); @@ -77,7 +83,7 @@ class WebPluginProxy : public WebPlugin { const gfx::Rect& clip_rect, bool visible, const SharedMemoryHandle& windowless_buffer, - const SharedMemoryLock& lock); + const SharedMemoryHandle& background_buffer); void CancelDocumentLoad(); @@ -90,12 +96,16 @@ class WebPluginProxy : public WebPlugin { private: bool Send(IPC::Message* msg); - // Called periodically so that we can paint windowless plugins. - void OnPaintTimerFired(); - // Updates the shared memory section where windowless plugins paint. - void SetWindowlessBuffer(const SharedMemoryHandle& handle, - const SharedMemoryLock& lock); + void SetWindowlessBuffer(const SharedMemoryHandle& windowless_buffer, + const SharedMemoryHandle& background_buffer); + + // Converts a shared memory section handle from the renderer process into a + // bitmap and hdc that are mapped to this process. + void ConvertBuffer(const SharedMemoryHandle& buffer, + ScopedHandle* shared_section, + ScopedBitmap* bitmap, + ScopedHDC* hdc); // Called when a plugin's origin moves, so that we can update the world // transform of the local HDC. @@ -109,20 +119,23 @@ class WebPluginProxy : public WebPlugin { NPObject* window_npobject_; NPObject* plugin_element_; WebPluginDelegateImpl* delegate_; + gfx::Rect damaged_rect_; + bool waiting_for_paint_; uint32 cp_browsing_context_; ScopedHandle modal_dialog_event_; - // Used to desynchronize windowless painting. We accumulate invalidates and - // paint into a shared buffer when our repeating timer fires. After painting - // we tell the renderer asynchronously and it paints from the buffer. This - // allows the renderer to paint without a blocking call, which improves - // performance, and lets us control the frame rate at which we paint. - gfx::Rect damaged_rect_; - base::RepeatingTimer<WebPluginProxy> paint_timer_; + // Variables used for desynchronized windowless plugin painting. See note in + // webplugin_delegate_proxy.h for how this works. + + // These hold the bitmap where the plugin draws. ScopedHandle windowless_shared_section_; ScopedBitmap windowless_bitmap_; ScopedHDC windowless_hdc_; - ScopedHandle windowless_buffer_lock_; + + // These hold the bitmap of the background image. + ScopedHandle background_shared_section_; + ScopedBitmap background_bitmap_; + ScopedHDC background_hdc_; }; #endif // CHROME_PLUGIN_PLUGIN_WEBPLUGIN_PROXY_H__ |