| Index: chrome/renderer/webplugin_delegate_proxy.cc
|
| ===================================================================
|
| --- chrome/renderer/webplugin_delegate_proxy.cc (revision 2736)
|
| +++ chrome/renderer/webplugin_delegate_proxy.cc (working copy)
|
| @@ -143,7 +143,9 @@
|
| 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 @@
|
| 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 @@
|
| 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::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 @@
|
| 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,34 +419,86 @@
|
| // 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);
|
| + }
|
|
|
| - BLENDFUNCTION m_bf;
|
| - m_bf.BlendOp = AC_SRC_OVER;
|
| - m_bf.BlendFlags = 0;
|
| - m_bf.SourceConstantAlpha = 255;
|
| - m_bf.AlphaFormat = AC_SRC_ALPHA;
|
| + 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);
|
| + }
|
|
|
| - 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);
|
| + 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);
|
|
|
| - BOOL result = ReleaseMutex(windowless_buffer_lock_);
|
| - DCHECK(result);
|
| + 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;
|
| + }
|
| +
|
| + XFORM xf;
|
| + if (!GetWorldTransform(hdc, &xf)) {
|
| + NOTREACHED();
|
| + return true;
|
| + }
|
| +
|
| + 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;
|
| + }
|
| +
|
| + return false;
|
| +}
|
| +
|
| void WebPluginDelegateProxy::Print(HDC hdc) {
|
| PluginMsg_PrintResponse_Params params = { 0 };
|
| Send(new PluginMsg_Print(instance_id_, ¶ms));
|
| @@ -488,11 +561,6 @@
|
| 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 @@
|
| plugin_->CancelResource(id);
|
| }
|
|
|
| -void WebPluginDelegateProxy::OnInvalidate() {
|
| - if (plugin_)
|
| - plugin_->Invalidate();
|
| -}
|
| +void WebPluginDelegateProxy::OnInvalidateRect(const gfx::Rect& rect) {
|
| + if (!plugin_)
|
| + return;
|
|
|
| -void WebPluginDelegateProxy::OnInvalidateRect(const gfx::Rect& rect) {
|
| - if (plugin_)
|
| - plugin_->InvalidateRect(rect);
|
| + invalidate_pending_ = true;
|
| + CopyFromTransportToBacking(rect);
|
| + plugin_->InvalidateRect(rect);
|
| }
|
|
|
| void WebPluginDelegateProxy::OnGetWindowScriptNPObject(
|
| @@ -616,6 +683,18 @@
|
| 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;
|
|
|