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

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

Issue 5040: Fix painting problem with transparent plugins because plugins were ignoring t... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 12 years, 2 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" 7 #include "base/gfx/bitmap_header.h"
8 #include "base/gfx/platform_device_win.h" 8 #include "base/gfx/platform_device_win.h"
9 #include "base/scoped_handle.h" 9 #include "base/scoped_handle.h"
10 #include "base/shared_memory.h" 10 #include "base/shared_memory.h"
11 #include "base/singleton.h" 11 #include "base/singleton.h"
12 #include "chrome/common/gfx/chrome_canvas.h" 12 #include "chrome/common/gfx/chrome_canvas.h"
13 #include "chrome/common/plugin_messages.h" 13 #include "chrome/common/plugin_messages.h"
14 #include "chrome/common/win_util.h" 14 #include "chrome/common/win_util.h"
15 #include "chrome/plugin/plugin_channel.h" 15 #include "chrome/plugin/plugin_channel.h"
16 #include "chrome/plugin/webplugin_delegate_stub.h" 16 #include "chrome/plugin/webplugin_delegate_stub.h"
17 #include "chrome/plugin/npobject_proxy.h" 17 #include "chrome/plugin/npobject_proxy.h"
18 #include "chrome/plugin/npobject_util.h" 18 #include "chrome/plugin/npobject_util.h"
19 #include "webkit/glue/plugins/webplugin_delegate_impl.h" 19 #include "webkit/glue/plugins/webplugin_delegate_impl.h"
20 20
21 // How many times per second we draw windowless plugins.
22 static const int kWindowlessPaintFPS = 30;
23
24 typedef std::map<CPBrowsingContext, WebPluginProxy*> ContextMap; 21 typedef std::map<CPBrowsingContext, WebPluginProxy*> ContextMap;
25 static ContextMap& GetContextMap() { 22 static ContextMap& GetContextMap() {
26 return *Singleton<ContextMap>::get(); 23 return *Singleton<ContextMap>::get();
27 } 24 }
28 25
29 WebPluginProxy::WebPluginProxy( 26 WebPluginProxy::WebPluginProxy(
30 PluginChannel* channel, 27 PluginChannel* channel,
31 int route_id, 28 int route_id,
32 WebPluginDelegateImpl* delegate, 29 WebPluginDelegateImpl* delegate,
33 HANDLE modal_dialog_event) 30 HANDLE modal_dialog_event)
34 : channel_(channel), 31 : channel_(channel),
35 route_id_(route_id), 32 route_id_(route_id),
36 cp_browsing_context_(0), 33 cp_browsing_context_(0),
37 window_npobject_(NULL), 34 window_npobject_(NULL),
38 plugin_element_(NULL), 35 plugin_element_(NULL),
39 delegate_(delegate) { 36 delegate_(delegate),
37 waiting_for_paint_(false) {
40 38
41 HANDLE event; 39 HANDLE event;
42 BOOL result = DuplicateHandle(channel->renderer_handle(), 40 BOOL result = DuplicateHandle(channel->renderer_handle(),
43 modal_dialog_event, 41 modal_dialog_event,
44 GetCurrentProcess(), 42 GetCurrentProcess(),
45 &event, 43 &event,
46 SYNCHRONIZE, 44 SYNCHRONIZE,
47 FALSE, 45 FALSE,
48 0); 46 0);
49 DCHECK(result) << "Couldn't duplicate the modal dialog handle for the plugin." ; 47 DCHECK(result) << "Couldn't duplicate the modal dialog handle for the plugin." ;
(...skipping 24 matching lines...) Expand all
74 Send(new PluginHostMsg_SetWindow(route_id_, window, 72 Send(new PluginHostMsg_SetWindow(route_id_, window,
75 pump_messages_event_for_renderer)); 73 pump_messages_event_for_renderer));
76 } 74 }
77 75
78 void WebPluginProxy::CancelResource(int id) { 76 void WebPluginProxy::CancelResource(int id) {
79 Send(new PluginHostMsg_CancelResource(route_id_, id)); 77 Send(new PluginHostMsg_CancelResource(route_id_, id));
80 resource_clients_.erase(id); 78 resource_clients_.erase(id);
81 } 79 }
82 80
83 void WebPluginProxy::Invalidate() { 81 void WebPluginProxy::Invalidate() {
84 Send(new PluginHostMsg_Invalidate(route_id_)); 82 gfx::Rect rect(0, 0, delegate_->rect().width(), delegate_->rect().height());
83 InvalidateRect(rect);
85 } 84 }
86 85
87 void WebPluginProxy::InvalidateRect(const gfx::Rect& rect) { 86 void WebPluginProxy::InvalidateRect(const gfx::Rect& rect) {
87 // Ignore NPN_InvalidateRect calls with empty rects.
88 if (rect.IsEmpty())
89 return;
90
88 damaged_rect_ = damaged_rect_.Union(rect); 91 damaged_rect_ = damaged_rect_.Union(rect);
89 if (!paint_timer_.IsRunning()) { 92 // Only send a single InvalidateRect message at a time. From DidPaint we
90 paint_timer_.Start(TimeDelta::FromMilliseconds(1000 / kWindowlessPaintFPS), 93 // will dispatch an additional InvalidateRect message if necessary.
91 this, &WebPluginProxy::OnPaintTimerFired); 94 if (!waiting_for_paint_) {
95 waiting_for_paint_ = true;
96 // Paint to the plugin bitmap and let the renderer know so it can update
97 // its backing store.
98 Paint(damaged_rect_);
99 Send(new PluginHostMsg_InvalidateRect(route_id_, damaged_rect_));
100 damaged_rect_ = gfx::Rect();
92 } 101 }
93 } 102 }
94 103
95 NPObject* WebPluginProxy::GetWindowScriptNPObject() { 104 NPObject* WebPluginProxy::GetWindowScriptNPObject() {
96 if (window_npobject_) 105 if (window_npobject_)
97 return NPN_RetainObject(window_npobject_); 106 return NPN_RetainObject(window_npobject_);
98 107
99 int npobject_route_id = channel_->GenerateRouteID(); 108 int npobject_route_id = channel_->GenerateRouteID();
100 bool success = false; 109 bool success = false;
101 void* npobject_ptr; 110 void* npobject_ptr;
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
183 WebPluginResourceClient* WebPluginProxy::GetResourceClient(int id) { 192 WebPluginResourceClient* WebPluginProxy::GetResourceClient(int id) {
184 ResourceClientMap::iterator iterator = resource_clients_.find(id); 193 ResourceClientMap::iterator iterator = resource_clients_.find(id);
185 if (iterator == resource_clients_.end()) { 194 if (iterator == resource_clients_.end()) {
186 NOTREACHED(); 195 NOTREACHED();
187 return NULL; 196 return NULL;
188 } 197 }
189 198
190 return iterator->second; 199 return iterator->second;
191 } 200 }
192 201
202 void WebPluginProxy::DidPaint() {
203 // If we have an accumulated damaged rect, then check to see if we need to
204 // send out another InvalidateRect message.
205 waiting_for_paint_ = false;
206 if (!damaged_rect_.IsEmpty())
207 InvalidateRect(damaged_rect_);
208 }
209
193 void WebPluginProxy::OnResourceCreated(int resource_id, HANDLE cookie) { 210 void WebPluginProxy::OnResourceCreated(int resource_id, HANDLE cookie) {
194 WebPluginResourceClient* resource_client = 211 WebPluginResourceClient* resource_client =
195 reinterpret_cast<WebPluginResourceClient*>(cookie); 212 reinterpret_cast<WebPluginResourceClient*>(cookie);
196 if (!resource_client) { 213 if (!resource_client) {
197 NOTREACHED(); 214 NOTREACHED();
198 return; 215 return;
199 } 216 }
200 217
201 DCHECK(resource_clients_.find(resource_id) == resource_clients_.end()); 218 DCHECK(resource_clients_.find(resource_id) == resource_clients_.end());
202 resource_clients_[resource_id] = resource_client; 219 resource_clients_[resource_id] = resource_client;
(...skipping 23 matching lines...) Expand all
226 243
227 params.is_file_data = is_file_data; 244 params.is_file_data = is_file_data;
228 params.notify = notify; 245 params.notify = notify;
229 params.url = url; 246 params.url = url;
230 params.notify_data = notify_data; 247 params.notify_data = notify_data;
231 params.popups_allowed = popups_allowed; 248 params.popups_allowed = popups_allowed;
232 249
233 Send(new PluginHostMsg_URLRequest(route_id_, params)); 250 Send(new PluginHostMsg_URLRequest(route_id_, params));
234 } 251 }
235 252
236 void WebPluginProxy::OnPaintTimerFired() { 253 void WebPluginProxy::Paint(const gfx::Rect& rect) {
237 if (!windowless_hdc_) 254 if (!windowless_hdc_)
238 return; 255 return;
239 256
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 257 // Clear the damaged area so that if the plugin doesn't paint there we won't
249 // end up with the old values. 258 // end up with the old values.
250 gfx::Rect offset_rect = damaged_rect_; 259 gfx::Rect offset_rect = rect;
251 offset_rect.Offset(delegate_->rect().x(), delegate_->rect().y()); 260 offset_rect.Offset(delegate_->rect().x(), delegate_->rect().y());
252 FillRect(windowless_hdc_, &offset_rect.ToRECT(), 261 if (!background_hdc_) {
253 static_cast<HBRUSH>(GetStockObject(BLACK_BRUSH))); 262 FillRect(windowless_hdc_, &offset_rect.ToRECT(),
263 static_cast<HBRUSH>(GetStockObject(BLACK_BRUSH)));
264 } else {
265 BitBlt(windowless_hdc_, offset_rect.x(), offset_rect.y(),
266 offset_rect.width(), offset_rect.height(), background_hdc_,
267 rect.x(), rect.y(), SRCCOPY);
268 }
254 269
255 // Before we send the invalidate, paint so that renderer uses the updated 270 // Before we send the invalidate, paint so that renderer uses the updated
256 // bitmap. 271 // bitmap.
257 delegate_->Paint(windowless_hdc_, damaged_rect_); 272 delegate_->Paint(windowless_hdc_, offset_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 } 273 }
264 274
265 void WebPluginProxy::UpdateGeometry( 275 void WebPluginProxy::UpdateGeometry(
266 const gfx::Rect& window_rect, 276 const gfx::Rect& window_rect,
267 const gfx::Rect& clip_rect, 277 const gfx::Rect& clip_rect,
268 bool visible, 278 bool visible,
269 const SharedMemoryHandle& windowless_buffer, 279 const SharedMemoryHandle& windowless_buffer,
270 const SharedMemoryLock& lock) { 280 const SharedMemoryHandle& background_buffer) {
281 gfx::Rect old = delegate_->rect();
271 bool moved = delegate_->rect().x() != window_rect.x() || 282 bool moved = delegate_->rect().x() != window_rect.x() ||
272 delegate_->rect().y() != window_rect.y(); 283 delegate_->rect().y() != window_rect.y();
273 delegate_->UpdateGeometry(window_rect, clip_rect, visible); 284 delegate_->UpdateGeometry(window_rect, clip_rect, visible);
274 if (windowless_buffer) { 285 if (windowless_buffer) {
275 // The plugin's rect changed, so now we have a new buffer to draw into. 286 // The plugin's rect changed, so now we have a new buffer to draw into.
276 SetWindowlessBuffer(windowless_buffer, lock); 287 SetWindowlessBuffer(windowless_buffer, background_buffer);
277 } else if (moved) { 288 } else if (moved) {
278 // The plugin moved, so update our world transform. 289 // The plugin moved, so update our world transform.
279 UpdateTransform(); 290 UpdateTransform();
280 } 291 }
281 } 292 }
282 293
283 void WebPluginProxy::SetWindowlessBuffer(const SharedMemoryHandle& handle, 294 void WebPluginProxy::SetWindowlessBuffer(
284 const SharedMemoryLock& lock) { 295 const SharedMemoryHandle& windowless_buffer,
296 const SharedMemoryHandle& background_buffer) {
285 // Convert the shared memory handle to a handle that works in our process, 297 // Convert the shared memory handle to a handle that works in our process,
286 // and then use that to create an HDC. 298 // and then use that to create an HDC.
287 windowless_shared_section_.Set(win_util::GetSectionFromProcess( 299 ConvertBuffer(windowless_buffer,
288 handle, channel_->renderer_handle(), false)); 300 &windowless_shared_section_,
289 if (!windowless_buffer_lock_) { 301 &windowless_bitmap_,
290 HANDLE dup_handle = NULL; 302 &windowless_hdc_);
291 DuplicateHandle(channel_->renderer_handle(), lock, GetCurrentProcess(), 303 if (background_buffer) {
292 &dup_handle, 0, FALSE, DUPLICATE_SAME_ACCESS); 304 ConvertBuffer(background_buffer,
293 windowless_buffer_lock_.Set(dup_handle); 305 &background_shared_section_,
306 &background_bitmap_,
307 &background_hdc_);
294 } 308 }
309 UpdateTransform();
310 }
295 311
296 if (windowless_shared_section_ == NULL || windowless_buffer_lock_ == NULL) { 312 void WebPluginProxy::ConvertBuffer(const SharedMemoryHandle& buffer,
313 ScopedHandle* shared_section,
314 ScopedBitmap* bitmap,
315 ScopedHDC* hdc) {
316 shared_section->Set(win_util::GetSectionFromProcess(
317 buffer, channel_->renderer_handle(), false));
318 if (shared_section->Get() == NULL) {
297 NOTREACHED(); 319 NOTREACHED();
298 return; 320 return;
299 } 321 }
300 322
301 void* data = NULL; 323 void* data = NULL;
302 HDC screen_dc = GetDC(NULL); 324 HDC screen_dc = GetDC(NULL);
303 BITMAPINFOHEADER bitmap_header; 325 BITMAPINFOHEADER bitmap_header;
304 gfx::CreateBitmapHeader(delegate_->rect().width(), 326 gfx::CreateBitmapHeader(delegate_->rect().width(),
305 delegate_->rect().height(), 327 delegate_->rect().height(),
306 &bitmap_header); 328 &bitmap_header);
307 windowless_bitmap_.Set(CreateDIBSection( 329 bitmap->Set(CreateDIBSection(
308 screen_dc, reinterpret_cast<const BITMAPINFO*>(&bitmap_header), 330 screen_dc, reinterpret_cast<const BITMAPINFO*>(&bitmap_header),
309 DIB_RGB_COLORS, &data, windowless_shared_section_, 0)); 331 DIB_RGB_COLORS, &data, shared_section->Get(), 0));
310 ReleaseDC(NULL, screen_dc); 332 ReleaseDC(NULL, screen_dc);
311 if (windowless_bitmap_ == NULL) { 333 if (bitmap->Get() == NULL) {
312 NOTREACHED(); 334 NOTREACHED();
313 return; 335 return;
314 } 336 }
315 337
316 windowless_hdc_.Set(CreateCompatibleDC(NULL)); 338 hdc->Set(CreateCompatibleDC(NULL));
317 if (windowless_hdc_ == NULL) { 339 if (hdc->Get() == NULL) {
318 NOTREACHED(); 340 NOTREACHED();
319 return; 341 return;
320 } 342 }
321 343
322 gfx::PlatformDeviceWin::InitializeDC(windowless_hdc_); 344 gfx::PlatformDeviceWin::InitializeDC(hdc->Get());
323 SelectObject(windowless_hdc_, windowless_bitmap_); 345 SelectObject(hdc->Get(), bitmap->Get());
324 UpdateTransform();
325 } 346 }
326 347
327 void WebPluginProxy::UpdateTransform() { 348 void WebPluginProxy::UpdateTransform() {
328 if (!windowless_hdc_) 349 if (!windowless_hdc_)
329 return; 350 return;
330 351
331 XFORM xf; 352 XFORM xf;
332 xf.eDx = static_cast<FLOAT>(-delegate_->rect().x()); 353 xf.eDx = static_cast<FLOAT>(-delegate_->rect().x());
333 xf.eDy = static_cast<FLOAT>(-delegate_->rect().y()); 354 xf.eDy = static_cast<FLOAT>(-delegate_->rect().y());
334 xf.eM11 = 1; 355 xf.eM11 = 1;
(...skipping 10 matching lines...) Expand all
345 void WebPluginProxy::InitiateHTTPRangeRequest(const char* url, 366 void WebPluginProxy::InitiateHTTPRangeRequest(const char* url,
346 const char* range_info, 367 const char* range_info,
347 void* existing_stream, 368 void* existing_stream,
348 bool notify_needed, 369 bool notify_needed,
349 HANDLE notify_data) { 370 HANDLE notify_data) {
350 371
351 Send(new PluginHostMsg_InitiateHTTPRangeRequest(route_id_, url, 372 Send(new PluginHostMsg_InitiateHTTPRangeRequest(route_id_, url,
352 range_info, existing_stream, 373 range_info, existing_stream,
353 notify_needed, notify_data)); 374 notify_needed, notify_data));
354 } 375 }
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