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

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 334 matching lines...) Expand 10 before | Expand all | Expand 10 after
395 396
396 bool flash = LowerCaseEqualsASCII(mime_type_, kFlashPluginSwfMimeType); 397 bool flash = LowerCaseEqualsASCII(mime_type_, kFlashPluginSwfMimeType);
397 bool silverlight = 398 bool silverlight =
398 StartsWithASCII(mime_type_, "application/x-silverlight", false); 399 StartsWithASCII(mime_type_, "application/x-silverlight", false);
399 for (size_t i = 0; i < arg_names.size(); ++i) { 400 for (size_t i = 0; i < arg_names.size(); ++i) {
400 if ((flash && LowerCaseEqualsASCII(arg_names[i], "wmode") && 401 if ((flash && LowerCaseEqualsASCII(arg_names[i], "wmode") &&
401 LowerCaseEqualsASCII(arg_values[i], "transparent")) || 402 LowerCaseEqualsASCII(arg_values[i], "transparent")) ||
402 (silverlight && LowerCaseEqualsASCII(arg_names[i], "background") && 403 (silverlight && LowerCaseEqualsASCII(arg_names[i], "background") &&
403 SilverlightColorIsTransparent(arg_values[i]))) { 404 SilverlightColorIsTransparent(arg_values[i]))) {
404 transparent_ = true; 405 transparent_ = true;
406 RenderThread::Get()->RecordUserMetrics("Plugin_Transparent");
405 } 407 }
406 } 408 }
407 params.load_manually = load_manually; 409 params.load_manually = load_manually;
408 410
409 plugin_ = plugin; 411 plugin_ = plugin;
410 412
411 result = false; 413 result = false;
412 IPC::Message* msg = new PluginMsg_Init(instance_id_, params, &result); 414 Send(new PluginMsg_Init(instance_id_, params, &result));
413 Send(msg);
414 415
415 if (!result) 416 if (!result)
416 LOG(ERROR) << "PluginMsg_Init returned false"; 417 LOG(ERROR) << "PluginMsg_Init returned false";
417 418
418 render_view_->RegisterPluginDelegate(this); 419 render_view_->RegisterPluginDelegate(this);
419 420
420 return result; 421 return result;
421 } 422 }
422 423
423 bool WebPluginDelegateProxy::Send(IPC::Message* msg) { 424 bool WebPluginDelegateProxy::Send(IPC::Message* msg) {
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after
661 &transport_stores_[0].canvas) || 662 &transport_stores_[0].canvas) ||
662 !CreateSharedBitmap(&transport_stores_[1].dib, 663 !CreateSharedBitmap(&transport_stores_[1].dib,
663 &transport_stores_[1].canvas) || 664 &transport_stores_[1].canvas) ||
664 (needs_background_store && 665 (needs_background_store &&
665 !CreateSharedBitmap(&background_store_.dib, 666 !CreateSharedBitmap(&background_store_.dib,
666 &background_store_.canvas))) { 667 &background_store_.canvas))) {
667 DCHECK(false); 668 DCHECK(false);
668 ResetWindowlessBitmaps(); 669 ResetWindowlessBitmaps();
669 return; 670 return;
670 } 671 }
672
673 if (needs_background_store &&
674 render_view_->is_accelerated_compositing_active()) {
675 // Better than grabage...
676 background_store_.canvas->drawColor(SK_ColorWHITE);
piman 2012/11/09 19:27:03 How about writing transparent pixels? If the plugi
jam 2012/11/09 22:50:24 Thanks, actually trying this out shows that NPAPI
677 }
671 } 678 }
672 } 679 }
673 } 680 }
674 681
675 SendUpdateGeometry(bitmaps_changed); 682 SendUpdateGeometry(bitmaps_changed);
676 } 683 }
677 684
678 void WebPluginDelegateProxy::ResetWindowlessBitmaps() { 685 void WebPluginDelegateProxy::ResetWindowlessBitmaps() {
679 transport_stores_[0].dib.reset(); 686 transport_stores_[0].dib.reset();
680 transport_stores_[1].dib.reset(); 687 transport_stores_[1].dib.reset();
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
755 } 762 }
756 763
757 if (!uses_shared_bitmaps_) 764 if (!uses_shared_bitmaps_)
758 return; 765 return;
759 766
760 // We got a paint before the plugin's coordinates, so there's no buffer to 767 // We got a paint before the plugin's coordinates, so there's no buffer to
761 // copy from. 768 // copy from.
762 if (!front_buffer_canvas()) 769 if (!front_buffer_canvas())
763 return; 770 return;
764 771
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; 772 gfx::Rect offset_rect = rect;
780 offset_rect.Offset(-plugin_rect_.x(), -plugin_rect_.y()); 773 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 774
787 bool background_changed = false; 775 bool background_changed = false;
788 if (background_store_.canvas.get() && BackgroundChanged(context, rect)) { 776 if (background_store_.canvas.get() && BackgroundChanged(canvas, rect) &&
777 // When accelerated compositing is used we don't have access to the
778 // page data under the plugin. This might result in painting glitches,
779 // but there's nothing we can do about that. This is mostly mitigiated
piman 2012/11/09 19:27:03 typo: mitigated
780 // by the fact that this is only for NPAPI plugins, and for Flash we use
781 // Pepper.
782 !render_view_->is_accelerated_compositing_active()) {
789 background_changed = true; 783 background_changed = true;
790 BlitContextToCanvas(background_store_.canvas.get(), canvas_rect, 784 SkIRect src_rect = gfx::RectToSkIRect(rect);
791 context, rect.origin()); 785 background_store_.canvas->drawBitmapRect(
786 canvas->getDevice()->accessBitmap(false),
787 &src_rect, gfx::RectToSkRect(offset_rect));
jam 2012/11/09 19:02:25 btw I found that somehow this isn't working on Lin
piman 2012/11/09 19:27:03 I'm not sure specifically, but I was going to ment
792 } 788 }
793 789
794 // transport_store_painted_ is really a bounding box, so in principle this 790 // 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 791 // check could falsely indicate that we don't need to paint offset_rect, but
796 // in practice it works fine. 792 // in practice it works fine.
797 if (background_changed || 793 if (background_changed || !transport_store_painted_.Contains(offset_rect)) {
798 !transport_store_painted_.Contains(offset_rect)) {
799 Send(new PluginMsg_Paint(instance_id_, offset_rect)); 794 Send(new PluginMsg_Paint(instance_id_, offset_rect));
800 // Since the plugin is not blocked on the renderer in this context, there is 795 // 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 796 // a chance that it will begin repainting the back-buffer before we complete
802 // capturing the data. Buffer flipping would increase that risk because 797 // capturing the data. Buffer flipping would increase that risk because
803 // geometry update is asynchronous, so we don't want to use buffer flipping 798 // geometry update is asynchronous, so we don't want to use buffer flipping
804 // here. 799 // here.
805 UpdateFrontBuffer(offset_rect, false); 800 UpdateFrontBuffer(offset_rect, false);
806 } 801 }
807 802
808 #if defined(OS_MACOSX) 803 const SkBitmap& bitmap =
809 // The canvases are flipped relative to the context, so flip the context's 804 front_buffer_canvas()->getDevice()->accessBitmap(false);
810 // coordinate space so that the blit unflips the content. 805 SkPaint paint;
811 CGContextSaveGState(context); 806 paint.setXfermodeMode(SkXfermode::kSrcATop_Mode);
812 CGContextScaleCTM(context, 1, -1); 807 SkIRect src_rect = gfx::RectToSkIRect(offset_rect);
813 rect.set_y(-rect.bottom()); 808 canvas->drawBitmapRect(bitmap,
814 #endif 809 &src_rect,
815 BlitCanvasToContext(context, 810 gfx::RectToSkRect(rect),
816 rect, 811 &paint);
817 front_buffer_canvas(),
818 offset_rect.origin());
819 #if defined(OS_MACOSX)
820 CGContextRestoreGState(context);
821 #endif
822 812
823 if (invalidate_pending_) { 813 if (invalidate_pending_) {
824 // Only send the PaintAck message if this paint is in response to an 814 // 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 815 // 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. 816 // to ensure only one process is using the transport dib at a time.
827 invalidate_pending_ = false; 817 invalidate_pending_ = false;
828 Send(new PluginMsg_DidPaint(instance_id_)); 818 Send(new PluginMsg_DidPaint(instance_id_));
829 } 819 }
830 } 820 }
831 821
832 bool WebPluginDelegateProxy::BackgroundChanged( 822 bool WebPluginDelegateProxy::BackgroundChanged(SkCanvas* canvas,
833 gfx::NativeDrawingContext context, 823 const gfx::Rect& rect) {
834 const gfx::Rect& rect) { 824 const SkMatrix& matrix = canvas->getTotalMatrix();
835 #if defined(OS_ANDROID) 825 const SkBitmap& page = canvas->getDevice()->accessBitmap(false);
836 NOTIMPLEMENTED(); 826 const SkBitmap& background =
837 #else 827 background_store_.canvas->getDevice()->accessBitmap(false);
838 #if defined(OS_WIN) 828 CHECK(page.bytesPerPixel() == background.bytesPerPixel());
piman 2012/11/09 19:27:03 Awesome thanks for removing this horrible per-plat
839 HBITMAP hbitmap = static_cast<HBITMAP>(GetCurrentObject(context, OBJ_BITMAP)); 829 int row_byte_size = rect.width() * page.bytesPerPixel();
piman 2012/11/09 19:27:03 This can get tricky with CSS transforms, in partic
840 if (hbitmap == NULL) { 830 for (int y = rect.y(); y < rect.bottom(); y++) {
841 NOTREACHED(); 831 SkPoint result;
842 return true; 832 matrix.mapXY(SkIntToScalar(rect.x()), SkIntToScalar(y), &result);
843 } 833 uint32_t* page_row_start = page.getAddr32(result.x(), result.y());
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 834
869 // getAddr32 doesn't use the translation units, so we have to subtract 835 // getAddr32 doesn't use the translation units, so we have to subtract
870 // the plugin origin from the coordinates. 836 // the plugin origin from the coordinates.
871 uint32_t* canvas_row_start = 837 uint32_t* background_row_start = background.getAddr32(
872 background_store_.canvas->getDevice()->accessBitmap(true).getAddr32( 838 rect.x() - plugin_rect_.x(), y - plugin_rect_.y());
873 check_rect.x() - plugin_rect_.x(), y - plugin_rect_.y()); 839 if (memcmp(page_row_start, background_row_start, row_byte_size) != 0)
874 if (memcmp(hdc_row_start, canvas_row_start, row_byte_size) != 0)
875 return true; 840 return true;
876 } 841 }
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; 842 return false;
981 } 843 }
982 844
983 NPObject* WebPluginDelegateProxy::GetPluginScriptableObject() { 845 NPObject* WebPluginDelegateProxy::GetPluginScriptableObject() {
984 if (npobject_) 846 if (npobject_)
985 return WebBindings::retainObject(npobject_); 847 return WebBindings::retainObject(npobject_);
986 848
987 int route_id = MSG_ROUTING_NONE; 849 int route_id = MSG_ROUTING_NONE;
988 Send(new PluginMsg_GetPluginScriptableObject(instance_id_, &route_id)); 850 Send(new PluginMsg_GetPluginScriptableObject(instance_id_, &route_id));
989 if (route_id == MSG_ROUTING_NONE) 851 if (route_id == MSG_ROUTING_NONE)
(...skipping 552 matching lines...) Expand 10 before | Expand all | Expand 10 after
1542 1404
1543 void WebPluginDelegateProxy::OnURLRedirectResponse(bool allow, 1405 void WebPluginDelegateProxy::OnURLRedirectResponse(bool allow,
1544 int resource_id) { 1406 int resource_id) {
1545 if (!plugin_) 1407 if (!plugin_)
1546 return; 1408 return;
1547 1409
1548 plugin_->URLRedirectResponse(allow, resource_id); 1410 plugin_->URLRedirectResponse(allow, resource_id);
1549 } 1411 }
1550 1412
1551 } // namespace content 1413 } // 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