summaryrefslogtreecommitdiffstats
path: root/content/renderer/webplugin_delegate_proxy.cc
diff options
context:
space:
mode:
authorjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-10 03:08:05 +0000
committerjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-10 03:08:05 +0000
commit4f15bb568f02c479ba56b40e3f17210414163d96 (patch)
treea1e0540cf16ed8c03dab17a015eb8d88ab32eb43 /content/renderer/webplugin_delegate_proxy.cc
parent5d047becad4bb3eda071d0e940e721a2e42e1bed (diff)
downloadchromium_src-4f15bb568f02c479ba56b40e3f17210414163d96.zip
chromium_src-4f15bb568f02c479ba56b40e3f17210414163d96.tar.gz
chromium_src-4f15bb568f02c479ba56b40e3f17210414163d96.tar.bz2
Get windowless plugins working when accelerated compositing is turned on by copying the buffers using skia instead of OS specific ways that need the platform device.
Also remove the code that kept the background buffer in sync with plugins since it's not necessary anymore. Looks like Flash and Silverlight support this correctly now. Review URL: https://codereview.chromium.org/11361170 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@167042 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/renderer/webplugin_delegate_proxy.cc')
-rw-r--r--content/renderer/webplugin_delegate_proxy.cc269
1 files changed, 13 insertions, 256 deletions
diff --git a/content/renderer/webplugin_delegate_proxy.cc b/content/renderer/webplugin_delegate_proxy.cc
index 3de0e7b..063649f 100644
--- a/content/renderer/webplugin_delegate_proxy.cc
+++ b/content/renderer/webplugin_delegate_proxy.cc
@@ -48,6 +48,7 @@
#include "ui/gfx/canvas.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/size.h"
+#include "ui/gfx/skia_util.h"
#include "webkit/glue/webkit_glue.h"
#include "webkit/plugins/npapi/webplugin.h"
#include "webkit/plugins/plugin_constants.h"
@@ -211,7 +212,6 @@ WebPluginDelegateProxy::WebPluginDelegateProxy(
npobject_(NULL),
sad_plugin_(NULL),
invalidate_pending_(false),
- transparent_(false),
front_buffer_index_(0),
page_url_(render_view_->webview()->mainFrame()->document().url()) {
}
@@ -279,33 +279,6 @@ void WebPluginDelegateProxy::PluginDestroyed() {
MessageLoop::current()->DeleteSoon(FROM_HERE, this);
}
-// Returns true if the given Silverlight 'background' value corresponds to
-// one that should make the plugin transparent. See:
-// http://msdn.microsoft.com/en-us/library/cc838148(VS.95).aspx
-// for possible values.
-static bool SilverlightColorIsTransparent(const std::string& color) {
- if (StartsWithASCII(color, "#", false)) {
- // If it's #ARGB or #AARRGGBB check the alpha; if not it's an RGB form and
- // it's not transparent.
- if ((color.length() == 5 && !StartsWithASCII(color, "#F", false)) ||
- (color.length() == 9 && !StartsWithASCII(color, "#FF", false)))
- return true;
- } else if (StartsWithASCII(color, "sc#", false)) {
- // It's either sc#A,R,G,B or sc#R,G,B; if the former, check the alpha.
- if (color.length() < 4)
- return false;
- std::string value_string = color.substr(3, std::string::npos);
- std::vector<std::string> components;
- base::SplitString(value_string, ',', &components);
- if (components.size() == 4 && !StartsWithASCII(components[0], "1", false))
- return true;
- } else if (LowerCaseEqualsASCII(color, "transparent")) {
- return true;
- }
- // Anything else is a named, opaque color or an RGB form with no alpha.
- return false;
-}
-
bool WebPluginDelegateProxy::Initialize(
const GURL& url,
const std::vector<std::string>& arg_names,
@@ -392,25 +365,12 @@ bool WebPluginDelegateProxy::Initialize(
params.arg_names = arg_names;
params.arg_values = arg_values;
params.host_render_view_routing_id = render_view_->routing_id();
-
- bool flash = LowerCaseEqualsASCII(mime_type_, kFlashPluginSwfMimeType);
- bool silverlight =
- StartsWithASCII(mime_type_, "application/x-silverlight", false);
- for (size_t i = 0; i < arg_names.size(); ++i) {
- if ((flash && LowerCaseEqualsASCII(arg_names[i], "wmode") &&
- LowerCaseEqualsASCII(arg_values[i], "transparent")) ||
- (silverlight && LowerCaseEqualsASCII(arg_names[i], "background") &&
- SilverlightColorIsTransparent(arg_values[i]))) {
- transparent_ = true;
- }
- }
params.load_manually = load_manually;
plugin_ = plugin;
result = false;
- IPC::Message* msg = new PluginMsg_Init(instance_id_, params, &result);
- Send(msg);
+ Send(new PluginMsg_Init(instance_id_, params, &result));
if (!result)
LOG(ERROR) << "PluginMsg_Init returned false";
@@ -580,8 +540,6 @@ void WebPluginDelegateProxy::SendUpdateGeometry(
param.windowless_buffer0 = TransportDIB::DefaultHandleValue();
param.windowless_buffer1 = TransportDIB::DefaultHandleValue();
param.windowless_buffer_index = back_buffer_index();
- param.background_buffer = TransportDIB::DefaultHandleValue();
- param.transparent = transparent_;
#if defined(OS_POSIX)
// If we're using POSIX mmap'd TransportDIBs, sending the handle across
@@ -599,11 +557,6 @@ void WebPluginDelegateProxy::SendUpdateGeometry(
CopyTransportDIBHandleForMessage(transport_stores_[1].dib->handle(),
&param.windowless_buffer1,
channel_host_->peer_pid());
-
- if (background_store_.dib.get())
- CopyTransportDIBHandleForMessage(background_store_.dib->handle(),
- &param.background_buffer,
- channel_host_->peer_pid());
}
IPC::Message* msg;
@@ -645,14 +598,6 @@ void WebPluginDelegateProxy::UpdateGeometry(const gfx::Rect& window_rect,
{
bitmaps_changed = true;
- bool needs_background_store = transparent_;
-#if defined(OS_MACOSX)
- // We don't support transparency under QuickDraw, and CoreGraphics
- // preserves transparency information (and does the compositing itself)
- // so plugins don't need access to the page background.
- needs_background_store = false;
-#endif
-
// Create a shared memory section that the plugin paints into
// asynchronously.
ResetWindowlessBitmaps();
@@ -660,10 +605,7 @@ void WebPluginDelegateProxy::UpdateGeometry(const gfx::Rect& window_rect,
if (!CreateSharedBitmap(&transport_stores_[0].dib,
&transport_stores_[0].canvas) ||
!CreateSharedBitmap(&transport_stores_[1].dib,
- &transport_stores_[1].canvas) ||
- (needs_background_store &&
- !CreateSharedBitmap(&background_store_.dib,
- &background_store_.canvas))) {
+ &transport_stores_[1].canvas)) {
DCHECK(false);
ResetWindowlessBitmaps();
return;
@@ -678,11 +620,9 @@ void WebPluginDelegateProxy::UpdateGeometry(const gfx::Rect& window_rect,
void WebPluginDelegateProxy::ResetWindowlessBitmaps() {
transport_stores_[0].dib.reset();
transport_stores_[1].dib.reset();
- background_store_.dib.reset();
transport_stores_[0].canvas.reset();
transport_stores_[1].canvas.reset();
- background_store_.canvas.reset();
transport_store_painted_ = gfx::Rect();
front_buffer_diff_ = gfx::Rect();
}
@@ -762,40 +702,13 @@ void WebPluginDelegateProxy::Paint(WebKit::WebCanvas* canvas,
if (!front_buffer_canvas())
return;
- // We're using the native OS APIs from here on out.
- if (!skia::SupportsPlatformPaint(canvas)) {
- // TODO(alokp): Implement this path.
- // This block will only get hit with --enable-accelerated-drawing flag.
- // With accelerated canvas, we do not have a bitmap that can be provided
- // to the plugin for compositing. We may have to implement a solution
- // described in crbug.com/12586.
- DLOG(WARNING) << "Could not paint plugin";
- return;
- }
- skia::ScopedPlatformPaint scoped_platform_paint(canvas);
- gfx::NativeDrawingContext context =
- scoped_platform_paint.GetPlatformSurface();
-
gfx::Rect offset_rect = rect;
offset_rect.Offset(-plugin_rect_.x(), -plugin_rect_.y());
- gfx::Rect canvas_rect = offset_rect;
-#if defined(OS_MACOSX)
- // The canvases are flipped relative to the context, so flip the rect too.
- FlipRectVerticallyWithHeight(&canvas_rect, plugin_rect_.height());
-#endif
-
- bool background_changed = false;
- if (background_store_.canvas.get() && BackgroundChanged(context, rect)) {
- background_changed = true;
- BlitContextToCanvas(background_store_.canvas.get(), canvas_rect,
- context, rect.origin());
- }
// transport_store_painted_ is really a bounding box, so in principle this
// check could falsely indicate that we don't need to paint offset_rect, but
// in practice it works fine.
- if (background_changed ||
- !transport_store_painted_.Contains(offset_rect)) {
+ if (!transport_store_painted_.Contains(offset_rect)) {
Send(new PluginMsg_Paint(instance_id_, offset_rect));
// Since the plugin is not blocked on the renderer in this context, there is
// a chance that it will begin repainting the back-buffer before we complete
@@ -805,20 +718,15 @@ void WebPluginDelegateProxy::Paint(WebKit::WebCanvas* canvas,
UpdateFrontBuffer(offset_rect, false);
}
-#if defined(OS_MACOSX)
- // The canvases are flipped relative to the context, so flip the context's
- // coordinate space so that the blit unflips the content.
- CGContextSaveGState(context);
- CGContextScaleCTM(context, 1, -1);
- rect.set_y(-rect.bottom());
-#endif
- BlitCanvasToContext(context,
- rect,
- front_buffer_canvas(),
- offset_rect.origin());
-#if defined(OS_MACOSX)
- CGContextRestoreGState(context);
-#endif
+ const SkBitmap& bitmap =
+ front_buffer_canvas()->getDevice()->accessBitmap(false);
+ SkPaint paint;
+ paint.setXfermodeMode(SkXfermode::kSrcATop_Mode);
+ SkIRect src_rect = gfx::RectToSkIRect(offset_rect);
+ canvas->drawBitmapRect(bitmap,
+ &src_rect,
+ gfx::RectToSkRect(rect),
+ &paint);
if (invalidate_pending_) {
// Only send the PaintAck message if this paint is in response to an
@@ -829,157 +737,6 @@ void WebPluginDelegateProxy::Paint(WebKit::WebCanvas* canvas,
}
}
-bool WebPluginDelegateProxy::BackgroundChanged(
- gfx::NativeDrawingContext context,
- const gfx::Rect& rect) {
-#if defined(OS_ANDROID)
- NOTIMPLEMENTED();
-#else
-#if defined(OS_WIN)
- HBITMAP hbitmap = static_cast<HBITMAP>(GetCurrentObject(context, OBJ_BITMAP));
- if (hbitmap == NULL) {
- NOTREACHED();
- return true;
- }
-
- BITMAP bitmap = { 0 };
- int result = GetObject(hbitmap, sizeof(bitmap), &bitmap);
- if (!result) {
- NOTREACHED();
- return true;
- }
-
- XFORM xf;
- if (!GetWorldTransform(context, &xf)) {
- NOTREACHED();
- return true;
- }
-
- // The damaged rect that we're given can be larger than the bitmap, so
- // intersect their rects first.
- gfx::Rect bitmap_rect(static_cast<int>(-xf.eDx), static_cast<int>(-xf.eDy),
- bitmap.bmWidth, bitmap.bmHeight);
- gfx::Rect check_rect = gfx::IntersectRects(rect, bitmap_rect);
- int row_byte_size = check_rect.width() * (bitmap.bmBitsPixel / 8);
- for (int y = check_rect.y(); y < check_rect.bottom(); y++) {
- char* hdc_row_start = static_cast<char*>(bitmap.bmBits) +
- (y + static_cast<int>(xf.eDy)) * bitmap.bmWidthBytes +
- (check_rect.x() + static_cast<int>(xf.eDx)) * (bitmap.bmBitsPixel / 8);
-
- // getAddr32 doesn't use the translation units, so we have to subtract
- // the plugin origin from the coordinates.
- uint32_t* canvas_row_start =
- background_store_.canvas->getDevice()->accessBitmap(true).getAddr32(
- check_rect.x() - plugin_rect_.x(), y - plugin_rect_.y());
- if (memcmp(hdc_row_start, canvas_row_start, row_byte_size) != 0)
- return true;
- }
-#else
-#if defined(OS_MACOSX)
- // If there is a translation on the content area context, we need to account
- // for it; the context may be a subset of the full content area with a
- // transform that makes the coordinates work out.
- CGAffineTransform transform = CGContextGetCTM(context);
- bool flipped = fabs(transform.d + 1) < 0.0001;
- CGFloat context_offset_x = -transform.tx;
- CGFloat context_offset_y = flipped ? transform.ty -
- CGBitmapContextGetHeight(context)
- : -transform.ty;
- gfx::Rect full_content_rect(context_offset_x, context_offset_y,
- CGBitmapContextGetWidth(context),
- CGBitmapContextGetHeight(context));
-#else
- cairo_surface_t* page_surface = cairo_get_target(context);
- DCHECK_EQ(cairo_surface_get_type(page_surface), CAIRO_SURFACE_TYPE_IMAGE);
- DCHECK_EQ(cairo_image_surface_get_format(page_surface), CAIRO_FORMAT_ARGB32);
-
- // Transform context coordinates into surface coordinates.
- double page_x_double = 0;
- double page_y_double = 0;
- cairo_device_to_user(context, &page_x_double, &page_y_double);
- gfx::Rect full_content_rect(static_cast<int>(page_x_double),
- static_cast<int>(page_y_double),
- cairo_image_surface_get_width(page_surface),
- cairo_image_surface_get_height(page_surface));
-#endif
- // According to comments in the Windows code, the damage rect that we're given
- // may project outside the image, so intersect their rects.
- gfx::Rect content_rect = gfx::IntersectRects(rect, full_content_rect);
-
-#if defined(OS_MACOSX)
- const unsigned char* page_bytes = static_cast<const unsigned char*>(
- CGBitmapContextGetData(context));
- int page_stride = CGBitmapContextGetBytesPerRow(context);
- int page_start_x = content_rect.x() - context_offset_x;
- int page_start_y = content_rect.y() - context_offset_y;
-
- skia::ScopedPlatformPaint scoped_platform_paint(
- background_store_.canvas.get());
- CGContextRef bg_context = scoped_platform_paint.GetPlatformSurface();
-
- DCHECK_EQ(CGBitmapContextGetBitsPerPixel(context),
- CGBitmapContextGetBitsPerPixel(bg_context));
- const unsigned char* bg_bytes = static_cast<const unsigned char*>(
- CGBitmapContextGetData(bg_context));
- int full_bg_width = CGBitmapContextGetWidth(bg_context);
- int full_bg_height = CGBitmapContextGetHeight(bg_context);
- int bg_stride = CGBitmapContextGetBytesPerRow(bg_context);
- int bg_last_row = CGBitmapContextGetHeight(bg_context) - 1;
-
- int bytes_per_pixel = CGBitmapContextGetBitsPerPixel(context) / 8;
-#else
- cairo_surface_flush(page_surface);
- const unsigned char* page_bytes = cairo_image_surface_get_data(page_surface);
- int page_stride = cairo_image_surface_get_stride(page_surface);
- int page_start_x = content_rect.x() - static_cast<int>(page_x_double);
- int page_start_y = content_rect.y() - static_cast<int>(page_y_double);
-
- skia::ScopedPlatformPaint scoped_platform_paint(
- background_store_.canvas.get());
- cairo_surface_t* bg_surface =cairo_get_target(
- scoped_platform_paint.GetPlatformSurface());
- DCHECK_EQ(cairo_surface_get_type(bg_surface), CAIRO_SURFACE_TYPE_IMAGE);
- DCHECK_EQ(cairo_image_surface_get_format(bg_surface), CAIRO_FORMAT_ARGB32);
- cairo_surface_flush(bg_surface);
- const unsigned char* bg_bytes = cairo_image_surface_get_data(bg_surface);
- int full_bg_width = cairo_image_surface_get_width(bg_surface);
- int full_bg_height = cairo_image_surface_get_height(bg_surface);
- int bg_stride = cairo_image_surface_get_stride(bg_surface);
-
- int bytes_per_pixel = 4; // ARGB32 = 4 bytes per pixel.
-#endif
-
- int damage_width = content_rect.width();
- int damage_height = content_rect.height();
-
- int bg_start_x = rect.x() - plugin_rect_.x();
- int bg_start_y = rect.y() - plugin_rect_.y();
- // The damage rect is supposed to have been intersected with the plugin rect;
- // double-check, since if it hasn't we'll walk off the end of the buffer.
- DCHECK_LE(bg_start_x + damage_width, full_bg_width);
- DCHECK_LE(bg_start_y + damage_height, full_bg_height);
-
- int bg_x_byte_offset = bg_start_x * bytes_per_pixel;
- int page_x_byte_offset = page_start_x * bytes_per_pixel;
- for (int row = 0; row < damage_height; ++row) {
- int page_offset = page_stride * (page_start_y + row) + page_x_byte_offset;
- int bg_y = bg_start_y + row;
-#if defined(OS_MACOSX)
- // The background buffer is upside down relative to the content.
- bg_y = bg_last_row - bg_y;
-#endif
- int bg_offset = bg_stride * bg_y + bg_x_byte_offset;
- if (memcmp(page_bytes + page_offset,
- bg_bytes + bg_offset,
- damage_width * bytes_per_pixel) != 0)
- return true;
- }
-#endif
-#endif // OS_ANDROID
-
- return false;
-}
-
NPObject* WebPluginDelegateProxy::GetPluginScriptableObject() {
if (npobject_)
return WebBindings::retainObject(npobject_);