summaryrefslogtreecommitdiffstats
path: root/chrome/renderer/webplugin_delegate_proxy.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/renderer/webplugin_delegate_proxy.cc')
-rw-r--r--chrome/renderer/webplugin_delegate_proxy.cc211
1 files changed, 145 insertions, 66 deletions
diff --git a/chrome/renderer/webplugin_delegate_proxy.cc b/chrome/renderer/webplugin_delegate_proxy.cc
index 5670bf7..1d6e8d21 100644
--- a/chrome/renderer/webplugin_delegate_proxy.cc
+++ b/chrome/renderer/webplugin_delegate_proxy.cc
@@ -143,7 +143,9 @@ WebPluginDelegateProxy::WebPluginDelegateProxy(const std::string& mime_type,
send_deferred_update_geometry_(false),
visible_(false),
sad_plugin_(NULL),
- window_script_object_(NULL) {
+ window_script_object_(NULL),
+ transparent_(false),
+ invalidate_pending_(false) {
}
WebPluginDelegateProxy::~WebPluginDelegateProxy() {
@@ -222,6 +224,11 @@ bool WebPluginDelegateProxy::Initialize(const GURL& url, char** argn,
for (int i = 0; i < argc; ++i) {
params.arg_names.push_back(argn[i]);
params.arg_values.push_back(argv[i]);
+
+ if (LowerCaseEqualsASCII(params.arg_names.back(), "wmode") &&
+ LowerCaseEqualsASCII(params.arg_values.back(), "transparent")) {
+ transparent_ = true;
+ }
}
params.load_manually = load_manually;
params.modal_dialog_event = render_view_->modal_dialog_event();
@@ -299,7 +306,6 @@ void WebPluginDelegateProxy::OnMessageReceived(const IPC::Message& msg) {
IPC_BEGIN_MESSAGE_MAP(WebPluginDelegateProxy, msg)
IPC_MESSAGE_HANDLER(PluginHostMsg_SetWindow, OnSetWindow)
IPC_MESSAGE_HANDLER(PluginHostMsg_CancelResource, OnCancelResource)
- IPC_MESSAGE_HANDLER(PluginHostMsg_Invalidate, OnInvalidate)
IPC_MESSAGE_HANDLER(PluginHostMsg_InvalidateRect, OnInvalidateRect)
IPC_MESSAGE_HANDLER(PluginHostMsg_GetWindowScriptNPObject,
OnGetWindowScriptNPObject)
@@ -322,21 +328,14 @@ void WebPluginDelegateProxy::OnMessageReceived(const IPC::Message& msg) {
}
void WebPluginDelegateProxy::OnChannelError() {
- OnInvalidate();
+ if (plugin_)
+ plugin_->Invalidate();
render_view_->PluginCrashed(plugin_path_);
}
-// Copied from render_widget.cc
-static size_t GetPaintBufSize(const gfx::Rect& rect) {
- // TODO(darin): protect against overflow
- return 4 * rect.width() * rect.height();
-}
-
void WebPluginDelegateProxy::UpdateGeometry(const gfx::Rect& window_rect,
const gfx::Rect& clip_rect,
bool visible) {
- bool moved = plugin_rect_.x() != window_rect.x() ||
- plugin_rect_.y() != window_rect.y();
plugin_rect_ = window_rect;
if (!windowless_) {
deferred_clip_rect_ = clip_rect;
@@ -345,43 +344,65 @@ void WebPluginDelegateProxy::UpdateGeometry(const gfx::Rect& window_rect,
return;
}
- HANDLE windowless_buffer_handle = NULL;
- if (!windowless_canvas_.get() ||
- (window_rect.width() != windowless_canvas_->getDevice()->width() ||
- window_rect.height() != windowless_canvas_->getDevice()->height())) {
- // Create a shared memory section that the plugin paints asynchronously.
- windowless_canvas_.reset();
- if (!windowless_buffer_lock_)
- windowless_buffer_lock_.Set(CreateMutex(NULL, FALSE, NULL));
- windowless_buffer_.reset(new SharedMemory());
- size_t size = GetPaintBufSize(plugin_rect_);
- if (!windowless_buffer_->Create(L"", false, true, size)) {
- DCHECK(false);
- windowless_buffer_.reset();
- return;
+ HANDLE transport_store_handle = NULL;
+ HANDLE background_store_handle = NULL;
+ if (!backing_store_canvas_.get() ||
+ (window_rect.width() != backing_store_canvas_->getDevice()->width() ||
+ window_rect.height() != backing_store_canvas_->getDevice()->height())) {
+ // Create a shared memory section that the plugin paints into
+ // asynchronously.
+ ResetWindowlessBitmaps();
+ if (!window_rect.IsEmpty()) {
+ if (!CreateBitmap(&backing_store_, &backing_store_canvas_) ||
+ !CreateBitmap(&transport_store_, &transport_store_canvas_) ||
+ (transparent_ &&
+ !CreateBitmap(&background_store_, &background_store_canvas_))) {
+ DCHECK(false);
+ ResetWindowlessBitmaps();
+ return;
+ }
+
+ transport_store_handle = transport_store_->handle();
+ if (background_store_.get())
+ background_store_handle = background_store_->handle();
}
-
- windowless_canvas_.reset(new gfx::PlatformCanvasWin(
- plugin_rect_.width(), plugin_rect_.height(), false,
- windowless_buffer_->handle()));
- windowless_canvas_->translate(static_cast<SkScalar>(-plugin_rect_.x()),
- static_cast<SkScalar>(-plugin_rect_.y()));
- windowless_canvas_->getTopPlatformDevice().accessBitmap(true).
- eraseARGB(0, 0, 0, 0);
- windowless_buffer_handle = windowless_buffer_->handle();
- } else if (moved) {
- windowless_canvas_->resetMatrix();
- windowless_canvas_->translate(static_cast<SkScalar>(-plugin_rect_.x()),
- static_cast<SkScalar>(-plugin_rect_.y()));
}
IPC::Message* msg = new PluginMsg_UpdateGeometry(
- instance_id_, window_rect, clip_rect, visible, windowless_buffer_handle,
- windowless_buffer_lock_);
+ instance_id_, window_rect, clip_rect, visible, transport_store_handle,
+ background_store_handle);
msg->set_unblock(true);
Send(msg);
}
+// Copied from render_widget.cc
+static size_t GetPaintBufSize(const gfx::Rect& rect) {
+ // TODO(darin): protect against overflow
+ return 4 * rect.width() * rect.height();
+}
+
+void WebPluginDelegateProxy::ResetWindowlessBitmaps() {
+ backing_store_.reset();
+ transport_store_.reset();
+ backing_store_canvas_.reset();
+ transport_store_canvas_.reset();
+ background_store_.reset();
+ background_store_canvas_.release();
+}
+
+bool WebPluginDelegateProxy::CreateBitmap(
+ scoped_ptr<SharedMemory>* memory,
+ scoped_ptr<gfx::PlatformCanvasWin>* canvas) {
+ size_t size = GetPaintBufSize(plugin_rect_);
+ memory->reset(new SharedMemory());
+ if (!(*memory)->Create(L"", false, true, size))
+ return false;
+
+ canvas->reset(new gfx::PlatformCanvasWin(
+ plugin_rect_.width(), plugin_rect_.height(), true, (*memory)->handle()));
+ return true;
+}
+
void WebPluginDelegateProxy::Paint(HDC hdc, const gfx::Rect& damaged_rect) {
// If the plugin is no longer connected (channel crashed) draw a crashed
// plugin bitmap
@@ -398,32 +419,84 @@ void WebPluginDelegateProxy::Paint(HDC hdc, const gfx::Rect& damaged_rect) {
// We shall use PrintWindow() to draw the window.
return;
}
- first_paint_ = false;
// We got a paint before the plugin's coordinates, so there's no buffer to
// copy from.
- if (!windowless_buffer_.get())
+ if (!backing_store_canvas_.get())
return;
// Limit the damaged rectangle to whatever is contained inside the plugin
// rectangle, as that's the rectangle that we'll bitblt to the hdc.
gfx::Rect rect = damaged_rect.Intersect(plugin_rect_);
- DWORD wait_result = WaitForSingleObject(windowless_buffer_lock_, INFINITE);
- DCHECK(wait_result == WAIT_OBJECT_0);
+ bool background_changed = false;
+ if (background_store_canvas_.get() && BackgroundChanged(hdc, rect)) {
+ background_changed = true;
+ HDC background_hdc =
+ background_store_canvas_->getTopPlatformDevice().getBitmapDC();
+ BitBlt(background_hdc, rect.x()-plugin_rect_.x(), rect.y()-plugin_rect_.y(),
+ rect.width(), rect.height(), hdc, rect.x(), rect.y(), SRCCOPY);
+ }
+
+ if (first_paint_ || background_changed) {
+ gfx::Rect offset_rect = rect;
+ offset_rect.Offset(-plugin_rect_.x(), -plugin_rect_.y());
+ Send(new PluginMsg_Paint(instance_id_, offset_rect));
+ CopyFromTransportToBacking(offset_rect);
+ }
+
+ first_paint_ = false;
+ HDC backing_hdc = backing_store_canvas_->getTopPlatformDevice().getBitmapDC();
+ BitBlt(hdc, rect.x(), rect.y(), rect.width(), rect.height(), backing_hdc,
+ rect.x()-plugin_rect_.x(), rect.y()-plugin_rect_.y(), SRCCOPY);
+
+ if (invalidate_pending_) {
+ // Only send the PaintAck message if this paint is in response to an
+ // invalidate from the plugin, since this message acts as an access token
+ // to ensure only one process is using the transport dib at a time.
+ invalidate_pending_ = false;
+ Send(new PluginMsg_DidPaint(instance_id_));
+ }
+}
+
+bool WebPluginDelegateProxy::BackgroundChanged(
+ HDC hdc,
+ const gfx::Rect& rect) {
+ HBITMAP hbitmap = static_cast<HBITMAP>(GetCurrentObject(hdc, OBJ_BITMAP));
+ if (hbitmap == NULL) {
+ NOTREACHED();
+ return true;
+ }
+
+ BITMAP bitmap = { 0 };
+ int result = GetObject(hbitmap, sizeof(bitmap), &bitmap);
+ if (!result) {
+ NOTREACHED();
+ return true;
+ }
- BLENDFUNCTION m_bf;
- m_bf.BlendOp = AC_SRC_OVER;
- m_bf.BlendFlags = 0;
- m_bf.SourceConstantAlpha = 255;
- m_bf.AlphaFormat = AC_SRC_ALPHA;
+ XFORM xf;
+ if (!GetWorldTransform(hdc, &xf)) {
+ NOTREACHED();
+ return true;
+ }
- HDC new_hdc = windowless_canvas_->getTopPlatformDevice().getBitmapDC();
- AlphaBlend(hdc, rect.x(), rect.y(), rect.width(), rect.height(),
- new_hdc, rect.x(), rect.y(), rect.width(), rect.height(), m_bf);
+ int row_byte_size = rect.width() * (bitmap.bmBitsPixel / 8);
+ for (int y = rect.y(); y < rect.bottom(); y++) {
+ char* hdc_row_start = static_cast<char*>(bitmap.bmBits) +
+ (y + static_cast<int>(xf.eDy)) * bitmap.bmWidthBytes +
+ (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(
+ rect.x() - plugin_rect_.x(), y - plugin_rect_.y());
+ if (memcmp(hdc_row_start, canvas_row_start, row_byte_size) != 0)
+ return true;
+ }
- BOOL result = ReleaseMutex(windowless_buffer_lock_);
- DCHECK(result);
+ return false;
}
void WebPluginDelegateProxy::Print(HDC hdc) {
@@ -488,11 +561,6 @@ int WebPluginDelegateProxy::GetProcessId() {
return channel_host_->peer_pid();
}
-HWND WebPluginDelegateProxy::GetWindowHandle() {
- NOTREACHED() << "GetWindowHandle can't be called on the proxy.";
- return NULL;
-}
-
void WebPluginDelegateProxy::OnSetWindow(
HWND window, HANDLE modal_loop_pump_messages_event) {
windowless_ = window == NULL;
@@ -508,14 +576,13 @@ void WebPluginDelegateProxy::OnCancelResource(int id) {
plugin_->CancelResource(id);
}
-void WebPluginDelegateProxy::OnInvalidate() {
- if (plugin_)
- plugin_->Invalidate();
-}
-
void WebPluginDelegateProxy::OnInvalidateRect(const gfx::Rect& rect) {
- if (plugin_)
- plugin_->InvalidateRect(rect);
+ if (!plugin_)
+ return;
+
+ invalidate_pending_ = true;
+ CopyFromTransportToBacking(rect);
+ plugin_->InvalidateRect(rect);
}
void WebPluginDelegateProxy::OnGetWindowScriptNPObject(
@@ -616,6 +683,18 @@ void WebPluginDelegateProxy::PaintSadPlugin(HDC hdc, const gfx::Rect& rect) {
return;
}
+void WebPluginDelegateProxy::CopyFromTransportToBacking(const gfx::Rect& rect) {
+ if (!backing_store_canvas_.get())
+ return;
+
+ // Copy the damaged rect from the transport bitmap to the backing store.
+ HDC backing = backing_store_canvas_->getTopPlatformDevice().getBitmapDC();
+ HDC transport = transport_store_canvas_->getTopPlatformDevice().getBitmapDC();
+
+ BitBlt(backing, rect.x(), rect.y(), rect.width(), rect.height(),
+ transport, rect.x(), rect.y(), SRCCOPY);
+}
+
void WebPluginDelegateProxy::OnHandleURLRequest(
const PluginHostMsg_URLRequest_Params& params) {
const char* data = NULL;