Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(163)

Side by Side Diff: chrome/plugin/webplugin_proxy.cc

Issue 3133: Desynchronize windowless plugin painting. This greatly improves the painting... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 12 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/plugin/webplugin_proxy.h ('k') | chrome/renderer/webplugin_delegate_proxy.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/plugin/webplugin_proxy.h" 5 #include "chrome/plugin/webplugin_proxy.h"
6 6
7 #include "base/gfx/bitmap_header.h"
8 #include "base/gfx/platform_device_win.h"
7 #include "base/scoped_handle.h" 9 #include "base/scoped_handle.h"
10 #include "base/shared_memory.h"
8 #include "base/singleton.h" 11 #include "base/singleton.h"
12 #include "chrome/common/gfx/chrome_canvas.h"
9 #include "chrome/common/plugin_messages.h" 13 #include "chrome/common/plugin_messages.h"
14 #include "chrome/common/win_util.h"
10 #include "chrome/plugin/plugin_channel.h" 15 #include "chrome/plugin/plugin_channel.h"
11 #include "chrome/plugin/webplugin_delegate_stub.h" 16 #include "chrome/plugin/webplugin_delegate_stub.h"
12 #include "chrome/plugin/npobject_proxy.h" 17 #include "chrome/plugin/npobject_proxy.h"
13 #include "chrome/plugin/npobject_util.h" 18 #include "chrome/plugin/npobject_util.h"
14 #include "webkit/glue/webplugin_delegate.h" 19 #include "webkit/glue/plugins/webplugin_delegate_impl.h"
20
21 // How many times per second we draw windowless plugins.
22 static const int kWindowlessPaintFPS = 30;
15 23
16 typedef std::map<CPBrowsingContext, WebPluginProxy*> ContextMap; 24 typedef std::map<CPBrowsingContext, WebPluginProxy*> ContextMap;
17 static ContextMap& GetContextMap() { 25 static ContextMap& GetContextMap() {
18 return *Singleton<ContextMap>::get(); 26 return *Singleton<ContextMap>::get();
19 } 27 }
20 28
21 WebPluginProxy::WebPluginProxy( 29 WebPluginProxy::WebPluginProxy(
22 PluginChannel* channel, 30 PluginChannel* channel,
23 int route_id, 31 int route_id,
24 WebPluginDelegate* delegate, 32 WebPluginDelegateImpl* delegate,
25 HANDLE modal_dialog_event) 33 HANDLE modal_dialog_event)
26 : channel_(channel), 34 : channel_(channel),
27 route_id_(route_id), 35 route_id_(route_id),
28 cp_browsing_context_(0), 36 cp_browsing_context_(0),
29 window_npobject_(NULL), 37 window_npobject_(NULL),
30 plugin_element_(NULL), 38 plugin_element_(NULL),
31 delegate_(delegate), 39 delegate_(delegate) {
32 waiting_for_paint_(false) {
33 40
34 HANDLE event; 41 HANDLE event;
35 BOOL result = DuplicateHandle(channel->renderer_handle(), 42 BOOL result = DuplicateHandle(channel->renderer_handle(),
36 modal_dialog_event, 43 modal_dialog_event,
37 GetCurrentProcess(), 44 GetCurrentProcess(),
38 &event, 45 &event,
39 SYNCHRONIZE, 46 SYNCHRONIZE,
40 FALSE, 47 FALSE,
41 0); 48 0);
42 DCHECK(result) << "Couldn't duplicate the modal dialog handle for the plugin." ; 49 DCHECK(result) << "Couldn't duplicate the modal dialog handle for the plugin." ;
(...skipping 28 matching lines...) Expand all
71 void WebPluginProxy::CancelResource(int id) { 78 void WebPluginProxy::CancelResource(int id) {
72 Send(new PluginHostMsg_CancelResource(route_id_, id)); 79 Send(new PluginHostMsg_CancelResource(route_id_, id));
73 resource_clients_.erase(id); 80 resource_clients_.erase(id);
74 } 81 }
75 82
76 void WebPluginProxy::Invalidate() { 83 void WebPluginProxy::Invalidate() {
77 Send(new PluginHostMsg_Invalidate(route_id_)); 84 Send(new PluginHostMsg_Invalidate(route_id_));
78 } 85 }
79 86
80 void WebPluginProxy::InvalidateRect(const gfx::Rect& rect) { 87 void WebPluginProxy::InvalidateRect(const gfx::Rect& rect) {
81 // Ignore NPN_InvalidateRect calls with empty rects. 88 damaged_rect_ = damaged_rect_.Union(rect);
82 if (rect.IsEmpty()) { 89 if (!paint_timer_.IsRunning()) {
83 return; 90 paint_timer_.Start(TimeDelta::FromMilliseconds(1000 / kWindowlessPaintFPS),
84 } 91 this, &WebPluginProxy::OnPaintTimerFired);
85 // Only send a single InvalidateRect message at a time. From WillPaint we
86 // will dispatch an additional InvalidateRect message if necessary.
87 if (waiting_for_paint_) {
88 damaged_rect_ = damaged_rect_.Union(rect);
89 } else {
90 waiting_for_paint_ = true;
91 Send(new PluginHostMsg_InvalidateRect(route_id_, rect));
92 } 92 }
93 } 93 }
94 94
95 NPObject* WebPluginProxy::GetWindowScriptNPObject() { 95 NPObject* WebPluginProxy::GetWindowScriptNPObject() {
96 if (window_npobject_) 96 if (window_npobject_)
97 return NPN_RetainObject(window_npobject_); 97 return NPN_RetainObject(window_npobject_);
98 98
99 int npobject_route_id = channel_->GenerateRouteID(); 99 int npobject_route_id = channel_->GenerateRouteID();
100 bool success = false; 100 bool success = false;
101 void* npobject_ptr; 101 void* npobject_ptr;
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
183 WebPluginResourceClient* WebPluginProxy::GetResourceClient(int id) { 183 WebPluginResourceClient* WebPluginProxy::GetResourceClient(int id) {
184 ResourceClientMap::iterator iterator = resource_clients_.find(id); 184 ResourceClientMap::iterator iterator = resource_clients_.find(id);
185 if (iterator == resource_clients_.end()) { 185 if (iterator == resource_clients_.end()) {
186 NOTREACHED(); 186 NOTREACHED();
187 return NULL; 187 return NULL;
188 } 188 }
189 189
190 return iterator->second; 190 return iterator->second;
191 } 191 }
192 192
193 void WebPluginProxy::WillPaint() {
194 // If we have an accumulated damaged rect, then check to see if we need to
195 // send out another InvalidateRect message.
196 waiting_for_paint_ = false;
197 if (!damaged_rect_.IsEmpty()) {
198 InvalidateRect(damaged_rect_);
199 damaged_rect_ = gfx::Rect();
200 }
201 }
202
203 void WebPluginProxy::OnResourceCreated(int resource_id, HANDLE cookie) { 193 void WebPluginProxy::OnResourceCreated(int resource_id, HANDLE cookie) {
204 WebPluginResourceClient* resource_client = 194 WebPluginResourceClient* resource_client =
205 reinterpret_cast<WebPluginResourceClient*>(cookie); 195 reinterpret_cast<WebPluginResourceClient*>(cookie);
206 if (!resource_client) { 196 if (!resource_client) {
207 NOTREACHED(); 197 NOTREACHED();
208 return; 198 return;
209 } 199 }
210 200
211 DCHECK(resource_clients_.find(resource_id) == resource_clients_.end()); 201 DCHECK(resource_clients_.find(resource_id) == resource_clients_.end());
212 resource_clients_[resource_id] = resource_client; 202 resource_clients_[resource_id] = resource_client;
(...skipping 23 matching lines...) Expand all
236 226
237 params.is_file_data = is_file_data; 227 params.is_file_data = is_file_data;
238 params.notify = notify; 228 params.notify = notify;
239 params.url = url; 229 params.url = url;
240 params.notify_data = notify_data; 230 params.notify_data = notify_data;
241 params.popups_allowed = popups_allowed; 231 params.popups_allowed = popups_allowed;
242 232
243 Send(new PluginHostMsg_URLRequest(route_id_, params)); 233 Send(new PluginHostMsg_URLRequest(route_id_, params));
244 } 234 }
245 235
236 void WebPluginProxy::OnPaintTimerFired() {
237 if (!windowless_hdc_)
238 return;
239
240 if (damaged_rect_.IsEmpty()) {
241 paint_timer_.Stop();
242 return;
243 }
244
245 DWORD wait_result = WaitForSingleObject(windowless_buffer_lock_, INFINITE);
246 DCHECK(wait_result == WAIT_OBJECT_0);
247
248 // Clear the damaged area so that if the plugin doesn't paint there we won't
249 // end up with the old values.
250 gfx::Rect offset_rect = damaged_rect_;
251 offset_rect.Offset(delegate_->rect().x(), delegate_->rect().y());
252 FillRect(windowless_hdc_, &offset_rect.ToRECT(),
253 static_cast<HBRUSH>(GetStockObject(BLACK_BRUSH)));
254
255 // Before we send the invalidate, paint so that renderer uses the updated
256 // bitmap.
257 delegate_->Paint(windowless_hdc_, damaged_rect_);
258 BOOL result = ReleaseMutex(windowless_buffer_lock_);
259 DCHECK(result);
260
261 Send(new PluginHostMsg_InvalidateRect(route_id_, damaged_rect_));
262 damaged_rect_ = gfx::Rect();
263 }
264
265 void WebPluginProxy::UpdateGeometry(
266 const gfx::Rect& window_rect,
267 const gfx::Rect& clip_rect,
268 bool visible,
269 const SharedMemoryHandle& windowless_buffer,
270 const SharedMemoryLock& lock) {
271 bool moved = delegate_->rect().x() != window_rect.x() ||
272 delegate_->rect().y() != window_rect.y();
273 delegate_->UpdateGeometry(window_rect, clip_rect, visible);
274 if (windowless_buffer) {
275 // The plugin's rect changed, so now we have a new buffer to draw into.
276 SetWindowlessBuffer(windowless_buffer, lock);
277 } else if (moved) {
278 // The plugin moved, so update our world transform.
279 UpdateTransform();
280 }
281 }
282
283 void WebPluginProxy::SetWindowlessBuffer(const SharedMemoryHandle& handle,
284 const SharedMemoryLock& lock) {
285 // Convert the shared memory handle to a handle that works in our process,
286 // and then use that to create an HDC.
287 windowless_shared_section_.Set(win_util::GetSectionFromProcess(
288 handle, channel_->renderer_handle(), false));
289 if (!windowless_buffer_lock_) {
290 HANDLE dup_handle = NULL;
291 DuplicateHandle(channel_->renderer_handle(), lock, GetCurrentProcess(),
292 &dup_handle, 0, FALSE, DUPLICATE_SAME_ACCESS);
293 windowless_buffer_lock_.Set(dup_handle);
294 }
295
296 if (windowless_shared_section_ == NULL || windowless_buffer_lock_ == NULL) {
297 NOTREACHED();
298 return;
299 }
300
301 void* data = NULL;
302 HDC screen_dc = GetDC(NULL);
303 BITMAPINFOHEADER bitmap_header;
304 gfx::CreateBitmapHeader(delegate_->rect().width(),
305 delegate_->rect().height(),
306 &bitmap_header);
307 windowless_bitmap_.Set(CreateDIBSection(
308 screen_dc, reinterpret_cast<const BITMAPINFO*>(&bitmap_header),
309 DIB_RGB_COLORS, &data, windowless_shared_section_, 0));
310 ReleaseDC(NULL, screen_dc);
311 if (windowless_bitmap_ == NULL) {
312 NOTREACHED();
313 return;
314 }
315
316 windowless_hdc_.Set(CreateCompatibleDC(NULL));
317 if (windowless_hdc_ == NULL) {
318 NOTREACHED();
319 return;
320 }
321
322 gfx::PlatformDeviceWin::InitializeDC(windowless_hdc_);
323 SelectObject(windowless_hdc_, windowless_bitmap_);
324 UpdateTransform();
325 }
326
327 void WebPluginProxy::UpdateTransform() {
328 if (!windowless_hdc_)
329 return;
330
331 XFORM xf;
332 xf.eDx = static_cast<FLOAT>(-delegate_->rect().x());
333 xf.eDy = static_cast<FLOAT>(-delegate_->rect().y());
334 xf.eM11 = 1;
335 xf.eM21 = 0;
336 xf.eM12 = 0;
337 xf.eM22 = 1;
338 SetWorldTransform(windowless_hdc_, &xf);
339 }
OLDNEW
« no previous file with comments | « chrome/plugin/webplugin_proxy.h ('k') | chrome/renderer/webplugin_delegate_proxy.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698