| Index: chrome/plugin/webplugin_proxy.cc
|
| ===================================================================
|
| --- chrome/plugin/webplugin_proxy.cc (revision 2736)
|
| +++ chrome/plugin/webplugin_proxy.cc (working copy)
|
| @@ -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 @@
|
| 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::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 @@
|
| 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 @@
|
| 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 @@
|
| 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 @@
|
| 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() {
|
|
|