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

Side by Side Diff: content/renderer/webplugin_delegate_proxy.cc

Issue 11361170: Get windowless plugins working when accelerated compositing is turned on. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 8 years, 1 month 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 | « content/renderer/webplugin_delegate_proxy.h ('k') | no next file » | 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) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "content/renderer/webplugin_delegate_proxy.h" 5 #include "content/renderer/webplugin_delegate_proxy.h"
6 6
7 #if defined(TOOLKIT_GTK) 7 #if defined(TOOLKIT_GTK)
8 #include <gtk/gtk.h> 8 #include <gtk/gtk.h>
9 #elif defined(USE_X11) 9 #elif defined(USE_X11)
10 #include <cairo/cairo.h> 10 #include <cairo/cairo.h>
(...skipping 30 matching lines...) Expand all
41 #include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h" 41 #include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h"
42 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" 42 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
43 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" 43 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
44 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" 44 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
45 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebDragData. h" 45 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebDragData. h"
46 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" 46 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h"
47 #include "ui/gfx/blit.h" 47 #include "ui/gfx/blit.h"
48 #include "ui/gfx/canvas.h" 48 #include "ui/gfx/canvas.h"
49 #include "ui/gfx/native_widget_types.h" 49 #include "ui/gfx/native_widget_types.h"
50 #include "ui/gfx/size.h" 50 #include "ui/gfx/size.h"
51 #include "ui/gfx/skia_util.h"
51 #include "webkit/glue/webkit_glue.h" 52 #include "webkit/glue/webkit_glue.h"
52 #include "webkit/plugins/npapi/webplugin.h" 53 #include "webkit/plugins/npapi/webplugin.h"
53 #include "webkit/plugins/plugin_constants.h" 54 #include "webkit/plugins/plugin_constants.h"
54 #include "webkit/plugins/sad_plugin.h" 55 #include "webkit/plugins/sad_plugin.h"
55 56
56 #if defined(OS_POSIX) 57 #if defined(OS_POSIX)
57 #include "ipc/ipc_channel_posix.h" 58 #include "ipc/ipc_channel_posix.h"
58 #endif 59 #endif
59 60
60 #if defined(OS_MACOSX) 61 #if defined(OS_MACOSX)
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
204 uses_compositor_(false), 205 uses_compositor_(false),
205 #elif defined(OS_WIN) 206 #elif defined(OS_WIN)
206 dummy_activation_window_(NULL), 207 dummy_activation_window_(NULL),
207 #endif 208 #endif
208 window_(gfx::kNullPluginWindow), 209 window_(gfx::kNullPluginWindow),
209 mime_type_(mime_type), 210 mime_type_(mime_type),
210 instance_id_(MSG_ROUTING_NONE), 211 instance_id_(MSG_ROUTING_NONE),
211 npobject_(NULL), 212 npobject_(NULL),
212 sad_plugin_(NULL), 213 sad_plugin_(NULL),
213 invalidate_pending_(false), 214 invalidate_pending_(false),
214 transparent_(false),
215 front_buffer_index_(0), 215 front_buffer_index_(0),
216 page_url_(render_view_->webview()->mainFrame()->document().url()) { 216 page_url_(render_view_->webview()->mainFrame()->document().url()) {
217 } 217 }
218 218
219 WebPluginDelegateProxy::~WebPluginDelegateProxy() { 219 WebPluginDelegateProxy::~WebPluginDelegateProxy() {
220 if (npobject_) 220 if (npobject_)
221 WebBindings::releaseObject(npobject_); 221 WebBindings::releaseObject(npobject_);
222 } 222 }
223 223
224 WebPluginDelegateProxy::SharedBitmap::SharedBitmap() {} 224 WebPluginDelegateProxy::SharedBitmap::SharedBitmap() {}
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
272 // the window script object. The window script object stub is unique to the 272 // the window script object. The window script object stub is unique to the
273 // plugin instance, so this won't affect other instances. 273 // plugin instance, so this won't affect other instances.
274 window_script_object_->DeleteSoon(); 274 window_script_object_->DeleteSoon();
275 } 275 }
276 276
277 plugin_ = NULL; 277 plugin_ = NULL;
278 278
279 MessageLoop::current()->DeleteSoon(FROM_HERE, this); 279 MessageLoop::current()->DeleteSoon(FROM_HERE, this);
280 } 280 }
281 281
282 // Returns true if the given Silverlight 'background' value corresponds to
283 // one that should make the plugin transparent. See:
284 // http://msdn.microsoft.com/en-us/library/cc838148(VS.95).aspx
285 // for possible values.
286 static bool SilverlightColorIsTransparent(const std::string& color) {
287 if (StartsWithASCII(color, "#", false)) {
288 // If it's #ARGB or #AARRGGBB check the alpha; if not it's an RGB form and
289 // it's not transparent.
290 if ((color.length() == 5 && !StartsWithASCII(color, "#F", false)) ||
291 (color.length() == 9 && !StartsWithASCII(color, "#FF", false)))
292 return true;
293 } else if (StartsWithASCII(color, "sc#", false)) {
294 // It's either sc#A,R,G,B or sc#R,G,B; if the former, check the alpha.
295 if (color.length() < 4)
296 return false;
297 std::string value_string = color.substr(3, std::string::npos);
298 std::vector<std::string> components;
299 base::SplitString(value_string, ',', &components);
300 if (components.size() == 4 && !StartsWithASCII(components[0], "1", false))
301 return true;
302 } else if (LowerCaseEqualsASCII(color, "transparent")) {
303 return true;
304 }
305 // Anything else is a named, opaque color or an RGB form with no alpha.
306 return false;
307 }
308
309 bool WebPluginDelegateProxy::Initialize( 282 bool WebPluginDelegateProxy::Initialize(
310 const GURL& url, 283 const GURL& url,
311 const std::vector<std::string>& arg_names, 284 const std::vector<std::string>& arg_names,
312 const std::vector<std::string>& arg_values, 285 const std::vector<std::string>& arg_values,
313 webkit::npapi::WebPlugin* plugin, 286 webkit::npapi::WebPlugin* plugin,
314 bool load_manually) { 287 bool load_manually) {
315 // TODO(shess): Attempt to work around http://crbug.com/97285 and 288 // TODO(shess): Attempt to work around http://crbug.com/97285 and
316 // http://crbug.com/141055 by retrying the connection. Reports seem 289 // http://crbug.com/141055 by retrying the connection. Reports seem
317 // to indicate that the plugin hasn't crashed, and that the problem 290 // to indicate that the plugin hasn't crashed, and that the problem
318 // is not 100% persistent. 291 // is not 100% persistent.
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
385 358
386 channel_host_->AddRoute(instance_id_, this, NULL); 359 channel_host_->AddRoute(instance_id_, this, NULL);
387 360
388 // Now tell the PluginInstance in the plugin process to initialize. 361 // Now tell the PluginInstance in the plugin process to initialize.
389 PluginMsg_Init_Params params; 362 PluginMsg_Init_Params params;
390 params.url = url; 363 params.url = url;
391 params.page_url = page_url_; 364 params.page_url = page_url_;
392 params.arg_names = arg_names; 365 params.arg_names = arg_names;
393 params.arg_values = arg_values; 366 params.arg_values = arg_values;
394 params.host_render_view_routing_id = render_view_->routing_id(); 367 params.host_render_view_routing_id = render_view_->routing_id();
395
396 bool flash = LowerCaseEqualsASCII(mime_type_, kFlashPluginSwfMimeType);
397 bool silverlight =
398 StartsWithASCII(mime_type_, "application/x-silverlight", false);
399 for (size_t i = 0; i < arg_names.size(); ++i) {
400 if ((flash && LowerCaseEqualsASCII(arg_names[i], "wmode") &&
401 LowerCaseEqualsASCII(arg_values[i], "transparent")) ||
402 (silverlight && LowerCaseEqualsASCII(arg_names[i], "background") &&
403 SilverlightColorIsTransparent(arg_values[i]))) {
404 transparent_ = true;
405 }
406 }
407 params.load_manually = load_manually; 368 params.load_manually = load_manually;
408 369
409 plugin_ = plugin; 370 plugin_ = plugin;
410 371
411 result = false; 372 result = false;
412 IPC::Message* msg = new PluginMsg_Init(instance_id_, params, &result); 373 Send(new PluginMsg_Init(instance_id_, params, &result));
413 Send(msg);
414 374
415 if (!result) 375 if (!result)
416 LOG(ERROR) << "PluginMsg_Init returned false"; 376 LOG(ERROR) << "PluginMsg_Init returned false";
417 377
418 render_view_->RegisterPluginDelegate(this); 378 render_view_->RegisterPluginDelegate(this);
419 379
420 return result; 380 return result;
421 } 381 }
422 382
423 bool WebPluginDelegateProxy::Send(IPC::Message* msg) { 383 bool WebPluginDelegateProxy::Send(IPC::Message* msg) {
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
573 } 533 }
574 534
575 void WebPluginDelegateProxy::SendUpdateGeometry( 535 void WebPluginDelegateProxy::SendUpdateGeometry(
576 bool bitmaps_changed) { 536 bool bitmaps_changed) {
577 PluginMsg_UpdateGeometry_Param param; 537 PluginMsg_UpdateGeometry_Param param;
578 param.window_rect = plugin_rect_; 538 param.window_rect = plugin_rect_;
579 param.clip_rect = clip_rect_; 539 param.clip_rect = clip_rect_;
580 param.windowless_buffer0 = TransportDIB::DefaultHandleValue(); 540 param.windowless_buffer0 = TransportDIB::DefaultHandleValue();
581 param.windowless_buffer1 = TransportDIB::DefaultHandleValue(); 541 param.windowless_buffer1 = TransportDIB::DefaultHandleValue();
582 param.windowless_buffer_index = back_buffer_index(); 542 param.windowless_buffer_index = back_buffer_index();
583 param.background_buffer = TransportDIB::DefaultHandleValue();
584 param.transparent = transparent_;
585 543
586 #if defined(OS_POSIX) 544 #if defined(OS_POSIX)
587 // If we're using POSIX mmap'd TransportDIBs, sending the handle across 545 // If we're using POSIX mmap'd TransportDIBs, sending the handle across
588 // IPC establishes a new mapping rather than just sending a window ID, 546 // IPC establishes a new mapping rather than just sending a window ID,
589 // so only do so if we've actually changed the shared memory bitmaps. 547 // so only do so if we've actually changed the shared memory bitmaps.
590 if (bitmaps_changed) 548 if (bitmaps_changed)
591 #endif 549 #endif
592 { 550 {
593 if (transport_stores_[0].dib.get()) 551 if (transport_stores_[0].dib.get())
594 CopyTransportDIBHandleForMessage(transport_stores_[0].dib->handle(), 552 CopyTransportDIBHandleForMessage(transport_stores_[0].dib->handle(),
595 &param.windowless_buffer0, 553 &param.windowless_buffer0,
596 channel_host_->peer_pid()); 554 channel_host_->peer_pid());
597 555
598 if (transport_stores_[1].dib.get()) 556 if (transport_stores_[1].dib.get())
599 CopyTransportDIBHandleForMessage(transport_stores_[1].dib->handle(), 557 CopyTransportDIBHandleForMessage(transport_stores_[1].dib->handle(),
600 &param.windowless_buffer1, 558 &param.windowless_buffer1,
601 channel_host_->peer_pid()); 559 channel_host_->peer_pid());
602
603 if (background_store_.dib.get())
604 CopyTransportDIBHandleForMessage(background_store_.dib->handle(),
605 &param.background_buffer,
606 channel_host_->peer_pid());
607 } 560 }
608 561
609 IPC::Message* msg; 562 IPC::Message* msg;
610 #if defined(OS_WIN) 563 #if defined(OS_WIN)
611 if (UseSynchronousGeometryUpdates()) { 564 if (UseSynchronousGeometryUpdates()) {
612 msg = new PluginMsg_UpdateGeometrySync(instance_id_, param); 565 msg = new PluginMsg_UpdateGeometrySync(instance_id_, param);
613 } else // NOLINT 566 } else // NOLINT
614 #endif 567 #endif
615 { 568 {
616 msg = new PluginMsg_UpdateGeometry(instance_id_, param); 569 msg = new PluginMsg_UpdateGeometry(instance_id_, param);
(...skipping 21 matching lines...) Expand all
638 591
639 bool bitmaps_changed = false; 592 bool bitmaps_changed = false;
640 593
641 if (uses_shared_bitmaps_) { 594 if (uses_shared_bitmaps_) {
642 if (!front_buffer_canvas() || 595 if (!front_buffer_canvas() ||
643 (window_rect.width() != front_buffer_canvas()->getDevice()->width() || 596 (window_rect.width() != front_buffer_canvas()->getDevice()->width() ||
644 window_rect.height() != front_buffer_canvas()->getDevice()->height())) 597 window_rect.height() != front_buffer_canvas()->getDevice()->height()))
645 { 598 {
646 bitmaps_changed = true; 599 bitmaps_changed = true;
647 600
648 bool needs_background_store = transparent_;
649 #if defined(OS_MACOSX)
650 // We don't support transparency under QuickDraw, and CoreGraphics
651 // preserves transparency information (and does the compositing itself)
652 // so plugins don't need access to the page background.
653 needs_background_store = false;
654 #endif
655
656 // Create a shared memory section that the plugin paints into 601 // Create a shared memory section that the plugin paints into
657 // asynchronously. 602 // asynchronously.
658 ResetWindowlessBitmaps(); 603 ResetWindowlessBitmaps();
659 if (!window_rect.IsEmpty()) { 604 if (!window_rect.IsEmpty()) {
660 if (!CreateSharedBitmap(&transport_stores_[0].dib, 605 if (!CreateSharedBitmap(&transport_stores_[0].dib,
661 &transport_stores_[0].canvas) || 606 &transport_stores_[0].canvas) ||
662 !CreateSharedBitmap(&transport_stores_[1].dib, 607 !CreateSharedBitmap(&transport_stores_[1].dib,
663 &transport_stores_[1].canvas) || 608 &transport_stores_[1].canvas)) {
664 (needs_background_store &&
665 !CreateSharedBitmap(&background_store_.dib,
666 &background_store_.canvas))) {
667 DCHECK(false); 609 DCHECK(false);
668 ResetWindowlessBitmaps(); 610 ResetWindowlessBitmaps();
669 return; 611 return;
670 } 612 }
671 } 613 }
672 } 614 }
673 } 615 }
674 616
675 SendUpdateGeometry(bitmaps_changed); 617 SendUpdateGeometry(bitmaps_changed);
676 } 618 }
677 619
678 void WebPluginDelegateProxy::ResetWindowlessBitmaps() { 620 void WebPluginDelegateProxy::ResetWindowlessBitmaps() {
679 transport_stores_[0].dib.reset(); 621 transport_stores_[0].dib.reset();
680 transport_stores_[1].dib.reset(); 622 transport_stores_[1].dib.reset();
681 background_store_.dib.reset();
682 623
683 transport_stores_[0].canvas.reset(); 624 transport_stores_[0].canvas.reset();
684 transport_stores_[1].canvas.reset(); 625 transport_stores_[1].canvas.reset();
685 background_store_.canvas.reset();
686 transport_store_painted_ = gfx::Rect(); 626 transport_store_painted_ = gfx::Rect();
687 front_buffer_diff_ = gfx::Rect(); 627 front_buffer_diff_ = gfx::Rect();
688 } 628 }
689 629
690 static size_t BitmapSizeForPluginRect(const gfx::Rect& plugin_rect) { 630 static size_t BitmapSizeForPluginRect(const gfx::Rect& plugin_rect) {
691 const size_t stride = 631 const size_t stride =
692 skia::PlatformCanvas::StrideForWidth(plugin_rect.width()); 632 skia::PlatformCanvas::StrideForWidth(plugin_rect.width());
693 return stride * plugin_rect.height(); 633 return stride * plugin_rect.height();
694 } 634 }
695 635
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
755 } 695 }
756 696
757 if (!uses_shared_bitmaps_) 697 if (!uses_shared_bitmaps_)
758 return; 698 return;
759 699
760 // We got a paint before the plugin's coordinates, so there's no buffer to 700 // We got a paint before the plugin's coordinates, so there's no buffer to
761 // copy from. 701 // copy from.
762 if (!front_buffer_canvas()) 702 if (!front_buffer_canvas())
763 return; 703 return;
764 704
765 // We're using the native OS APIs from here on out.
766 if (!skia::SupportsPlatformPaint(canvas)) {
767 // TODO(alokp): Implement this path.
768 // This block will only get hit with --enable-accelerated-drawing flag.
769 // With accelerated canvas, we do not have a bitmap that can be provided
770 // to the plugin for compositing. We may have to implement a solution
771 // described in crbug.com/12586.
772 DLOG(WARNING) << "Could not paint plugin";
773 return;
774 }
775 skia::ScopedPlatformPaint scoped_platform_paint(canvas);
776 gfx::NativeDrawingContext context =
777 scoped_platform_paint.GetPlatformSurface();
778
779 gfx::Rect offset_rect = rect; 705 gfx::Rect offset_rect = rect;
780 offset_rect.Offset(-plugin_rect_.x(), -plugin_rect_.y()); 706 offset_rect.Offset(-plugin_rect_.x(), -plugin_rect_.y());
781 gfx::Rect canvas_rect = offset_rect;
782 #if defined(OS_MACOSX)
783 // The canvases are flipped relative to the context, so flip the rect too.
784 FlipRectVerticallyWithHeight(&canvas_rect, plugin_rect_.height());
785 #endif
786
787 bool background_changed = false;
788 if (background_store_.canvas.get() && BackgroundChanged(context, rect)) {
789 background_changed = true;
790 BlitContextToCanvas(background_store_.canvas.get(), canvas_rect,
791 context, rect.origin());
792 }
793 707
794 // transport_store_painted_ is really a bounding box, so in principle this 708 // transport_store_painted_ is really a bounding box, so in principle this
795 // check could falsely indicate that we don't need to paint offset_rect, but 709 // check could falsely indicate that we don't need to paint offset_rect, but
796 // in practice it works fine. 710 // in practice it works fine.
797 if (background_changed || 711 if (!transport_store_painted_.Contains(offset_rect)) {
798 !transport_store_painted_.Contains(offset_rect)) {
799 Send(new PluginMsg_Paint(instance_id_, offset_rect)); 712 Send(new PluginMsg_Paint(instance_id_, offset_rect));
800 // Since the plugin is not blocked on the renderer in this context, there is 713 // Since the plugin is not blocked on the renderer in this context, there is
801 // a chance that it will begin repainting the back-buffer before we complete 714 // a chance that it will begin repainting the back-buffer before we complete
802 // capturing the data. Buffer flipping would increase that risk because 715 // capturing the data. Buffer flipping would increase that risk because
803 // geometry update is asynchronous, so we don't want to use buffer flipping 716 // geometry update is asynchronous, so we don't want to use buffer flipping
804 // here. 717 // here.
805 UpdateFrontBuffer(offset_rect, false); 718 UpdateFrontBuffer(offset_rect, false);
806 } 719 }
807 720
808 #if defined(OS_MACOSX) 721 const SkBitmap& bitmap =
809 // The canvases are flipped relative to the context, so flip the context's 722 front_buffer_canvas()->getDevice()->accessBitmap(false);
810 // coordinate space so that the blit unflips the content. 723 SkPaint paint;
811 CGContextSaveGState(context); 724 paint.setXfermodeMode(SkXfermode::kSrcATop_Mode);
812 CGContextScaleCTM(context, 1, -1); 725 SkIRect src_rect = gfx::RectToSkIRect(offset_rect);
813 rect.set_y(-rect.bottom()); 726 canvas->drawBitmapRect(bitmap,
814 #endif 727 &src_rect,
815 BlitCanvasToContext(context, 728 gfx::RectToSkRect(rect),
816 rect, 729 &paint);
817 front_buffer_canvas(),
818 offset_rect.origin());
819 #if defined(OS_MACOSX)
820 CGContextRestoreGState(context);
821 #endif
822 730
823 if (invalidate_pending_) { 731 if (invalidate_pending_) {
824 // Only send the PaintAck message if this paint is in response to an 732 // Only send the PaintAck message if this paint is in response to an
825 // invalidate from the plugin, since this message acts as an access token 733 // invalidate from the plugin, since this message acts as an access token
826 // to ensure only one process is using the transport dib at a time. 734 // to ensure only one process is using the transport dib at a time.
827 invalidate_pending_ = false; 735 invalidate_pending_ = false;
828 Send(new PluginMsg_DidPaint(instance_id_)); 736 Send(new PluginMsg_DidPaint(instance_id_));
829 } 737 }
830 } 738 }
831 739
832 bool WebPluginDelegateProxy::BackgroundChanged(
833 gfx::NativeDrawingContext context,
834 const gfx::Rect& rect) {
835 #if defined(OS_ANDROID)
836 NOTIMPLEMENTED();
837 #else
838 #if defined(OS_WIN)
839 HBITMAP hbitmap = static_cast<HBITMAP>(GetCurrentObject(context, OBJ_BITMAP));
840 if (hbitmap == NULL) {
841 NOTREACHED();
842 return true;
843 }
844
845 BITMAP bitmap = { 0 };
846 int result = GetObject(hbitmap, sizeof(bitmap), &bitmap);
847 if (!result) {
848 NOTREACHED();
849 return true;
850 }
851
852 XFORM xf;
853 if (!GetWorldTransform(context, &xf)) {
854 NOTREACHED();
855 return true;
856 }
857
858 // The damaged rect that we're given can be larger than the bitmap, so
859 // intersect their rects first.
860 gfx::Rect bitmap_rect(static_cast<int>(-xf.eDx), static_cast<int>(-xf.eDy),
861 bitmap.bmWidth, bitmap.bmHeight);
862 gfx::Rect check_rect = gfx::IntersectRects(rect, bitmap_rect);
863 int row_byte_size = check_rect.width() * (bitmap.bmBitsPixel / 8);
864 for (int y = check_rect.y(); y < check_rect.bottom(); y++) {
865 char* hdc_row_start = static_cast<char*>(bitmap.bmBits) +
866 (y + static_cast<int>(xf.eDy)) * bitmap.bmWidthBytes +
867 (check_rect.x() + static_cast<int>(xf.eDx)) * (bitmap.bmBitsPixel / 8);
868
869 // getAddr32 doesn't use the translation units, so we have to subtract
870 // the plugin origin from the coordinates.
871 uint32_t* canvas_row_start =
872 background_store_.canvas->getDevice()->accessBitmap(true).getAddr32(
873 check_rect.x() - plugin_rect_.x(), y - plugin_rect_.y());
874 if (memcmp(hdc_row_start, canvas_row_start, row_byte_size) != 0)
875 return true;
876 }
877 #else
878 #if defined(OS_MACOSX)
879 // If there is a translation on the content area context, we need to account
880 // for it; the context may be a subset of the full content area with a
881 // transform that makes the coordinates work out.
882 CGAffineTransform transform = CGContextGetCTM(context);
883 bool flipped = fabs(transform.d + 1) < 0.0001;
884 CGFloat context_offset_x = -transform.tx;
885 CGFloat context_offset_y = flipped ? transform.ty -
886 CGBitmapContextGetHeight(context)
887 : -transform.ty;
888 gfx::Rect full_content_rect(context_offset_x, context_offset_y,
889 CGBitmapContextGetWidth(context),
890 CGBitmapContextGetHeight(context));
891 #else
892 cairo_surface_t* page_surface = cairo_get_target(context);
893 DCHECK_EQ(cairo_surface_get_type(page_surface), CAIRO_SURFACE_TYPE_IMAGE);
894 DCHECK_EQ(cairo_image_surface_get_format(page_surface), CAIRO_FORMAT_ARGB32);
895
896 // Transform context coordinates into surface coordinates.
897 double page_x_double = 0;
898 double page_y_double = 0;
899 cairo_device_to_user(context, &page_x_double, &page_y_double);
900 gfx::Rect full_content_rect(static_cast<int>(page_x_double),
901 static_cast<int>(page_y_double),
902 cairo_image_surface_get_width(page_surface),
903 cairo_image_surface_get_height(page_surface));
904 #endif
905 // According to comments in the Windows code, the damage rect that we're given
906 // may project outside the image, so intersect their rects.
907 gfx::Rect content_rect = gfx::IntersectRects(rect, full_content_rect);
908
909 #if defined(OS_MACOSX)
910 const unsigned char* page_bytes = static_cast<const unsigned char*>(
911 CGBitmapContextGetData(context));
912 int page_stride = CGBitmapContextGetBytesPerRow(context);
913 int page_start_x = content_rect.x() - context_offset_x;
914 int page_start_y = content_rect.y() - context_offset_y;
915
916 skia::ScopedPlatformPaint scoped_platform_paint(
917 background_store_.canvas.get());
918 CGContextRef bg_context = scoped_platform_paint.GetPlatformSurface();
919
920 DCHECK_EQ(CGBitmapContextGetBitsPerPixel(context),
921 CGBitmapContextGetBitsPerPixel(bg_context));
922 const unsigned char* bg_bytes = static_cast<const unsigned char*>(
923 CGBitmapContextGetData(bg_context));
924 int full_bg_width = CGBitmapContextGetWidth(bg_context);
925 int full_bg_height = CGBitmapContextGetHeight(bg_context);
926 int bg_stride = CGBitmapContextGetBytesPerRow(bg_context);
927 int bg_last_row = CGBitmapContextGetHeight(bg_context) - 1;
928
929 int bytes_per_pixel = CGBitmapContextGetBitsPerPixel(context) / 8;
930 #else
931 cairo_surface_flush(page_surface);
932 const unsigned char* page_bytes = cairo_image_surface_get_data(page_surface);
933 int page_stride = cairo_image_surface_get_stride(page_surface);
934 int page_start_x = content_rect.x() - static_cast<int>(page_x_double);
935 int page_start_y = content_rect.y() - static_cast<int>(page_y_double);
936
937 skia::ScopedPlatformPaint scoped_platform_paint(
938 background_store_.canvas.get());
939 cairo_surface_t* bg_surface =cairo_get_target(
940 scoped_platform_paint.GetPlatformSurface());
941 DCHECK_EQ(cairo_surface_get_type(bg_surface), CAIRO_SURFACE_TYPE_IMAGE);
942 DCHECK_EQ(cairo_image_surface_get_format(bg_surface), CAIRO_FORMAT_ARGB32);
943 cairo_surface_flush(bg_surface);
944 const unsigned char* bg_bytes = cairo_image_surface_get_data(bg_surface);
945 int full_bg_width = cairo_image_surface_get_width(bg_surface);
946 int full_bg_height = cairo_image_surface_get_height(bg_surface);
947 int bg_stride = cairo_image_surface_get_stride(bg_surface);
948
949 int bytes_per_pixel = 4; // ARGB32 = 4 bytes per pixel.
950 #endif
951
952 int damage_width = content_rect.width();
953 int damage_height = content_rect.height();
954
955 int bg_start_x = rect.x() - plugin_rect_.x();
956 int bg_start_y = rect.y() - plugin_rect_.y();
957 // The damage rect is supposed to have been intersected with the plugin rect;
958 // double-check, since if it hasn't we'll walk off the end of the buffer.
959 DCHECK_LE(bg_start_x + damage_width, full_bg_width);
960 DCHECK_LE(bg_start_y + damage_height, full_bg_height);
961
962 int bg_x_byte_offset = bg_start_x * bytes_per_pixel;
963 int page_x_byte_offset = page_start_x * bytes_per_pixel;
964 for (int row = 0; row < damage_height; ++row) {
965 int page_offset = page_stride * (page_start_y + row) + page_x_byte_offset;
966 int bg_y = bg_start_y + row;
967 #if defined(OS_MACOSX)
968 // The background buffer is upside down relative to the content.
969 bg_y = bg_last_row - bg_y;
970 #endif
971 int bg_offset = bg_stride * bg_y + bg_x_byte_offset;
972 if (memcmp(page_bytes + page_offset,
973 bg_bytes + bg_offset,
974 damage_width * bytes_per_pixel) != 0)
975 return true;
976 }
977 #endif
978 #endif // OS_ANDROID
979
980 return false;
981 }
982
983 NPObject* WebPluginDelegateProxy::GetPluginScriptableObject() { 740 NPObject* WebPluginDelegateProxy::GetPluginScriptableObject() {
984 if (npobject_) 741 if (npobject_)
985 return WebBindings::retainObject(npobject_); 742 return WebBindings::retainObject(npobject_);
986 743
987 int route_id = MSG_ROUTING_NONE; 744 int route_id = MSG_ROUTING_NONE;
988 Send(new PluginMsg_GetPluginScriptableObject(instance_id_, &route_id)); 745 Send(new PluginMsg_GetPluginScriptableObject(instance_id_, &route_id));
989 if (route_id == MSG_ROUTING_NONE) 746 if (route_id == MSG_ROUTING_NONE)
990 return NULL; 747 return NULL;
991 748
992 npobject_ = NPObjectProxy::Create( 749 npobject_ = NPObjectProxy::Create(
(...skipping 549 matching lines...) Expand 10 before | Expand all | Expand 10 after
1542 1299
1543 void WebPluginDelegateProxy::OnURLRedirectResponse(bool allow, 1300 void WebPluginDelegateProxy::OnURLRedirectResponse(bool allow,
1544 int resource_id) { 1301 int resource_id) {
1545 if (!plugin_) 1302 if (!plugin_)
1546 return; 1303 return;
1547 1304
1548 plugin_->URLRedirectResponse(allow, resource_id); 1305 plugin_->URLRedirectResponse(allow, resource_id);
1549 } 1306 }
1550 1307
1551 } // namespace content 1308 } // namespace content
OLDNEW
« no previous file with comments | « content/renderer/webplugin_delegate_proxy.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698