| Index: content/browser/renderer_host/render_widget_host_impl.cc
|
| diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
|
| index d4779ae3cfd7a9dea43416593bc876ec2beaf7ef..60197e5dbffdc072a3d08cd67c2f40d805c0193f 100644
|
| --- a/content/browser/renderer_host/render_widget_host_impl.cc
|
| +++ b/content/browser/renderer_host/render_widget_host_impl.cc
|
| @@ -65,7 +65,7 @@ namespace {
|
| // PaintRect message, when our backing-store is invalid, before giving up and
|
| // returning a null or incorrectly sized backing-store from GetBackingStore.
|
| // This timeout impacts the "choppiness" of our window resize perf.
|
| -static const int kPaintMsgTimeoutMS = 40;
|
| +static const int kPaintMsgTimeoutMS = 50;
|
|
|
| // How long to wait before we consider a renderer hung.
|
| static const int kHungRendererDelayMs = 20000;
|
| @@ -119,6 +119,7 @@ RenderWidgetHostImpl::RenderWidgetHostImpl(RenderProcessHost* process,
|
| is_unresponsive_(false),
|
| in_flight_event_count_(0),
|
| in_get_backing_store_(false),
|
| + abort_get_backing_store_(false),
|
| view_being_painted_(false),
|
| ignore_input_events_(false),
|
| text_direction_updated_(false),
|
| @@ -257,6 +258,8 @@ bool RenderWidgetHostImpl::OnMessageReceived(const IPC::Message &msg) {
|
| IPC_MESSAGE_HANDLER(ViewHostMsg_RequestMove, OnMsgRequestMove)
|
| IPC_MESSAGE_HANDLER(ViewHostMsg_SetTooltipText, OnMsgSetTooltipText)
|
| IPC_MESSAGE_HANDLER(ViewHostMsg_PaintAtSize_ACK, OnMsgPaintAtSizeAck)
|
| + IPC_MESSAGE_HANDLER(ViewHostMsg_CompositorSurfaceBuffersSwapped,
|
| + OnCompositorSurfaceBuffersSwapped)
|
| IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateRect, OnMsgUpdateRect)
|
| IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateIsDelayed, OnMsgUpdateIsDelayed)
|
| IPC_MESSAGE_HANDLER(ViewHostMsg_HandleInputEvent_ACK, OnMsgInputEventAck)
|
| @@ -574,10 +577,38 @@ void RenderWidgetHostImpl::PaintAtSize(TransportDIB::Handle dib_handle,
|
| page_size, desired_size));
|
| }
|
|
|
| +bool RenderWidgetHostImpl::TryGetBackingStore(const gfx::Size& desired_size,
|
| + BackingStore** backing_store) {
|
| + // Check if the view has an accelerated surface of the desired size.
|
| + if (view_->HasAcceleratedSurface(desired_size)) {
|
| + *backing_store = NULL;
|
| + return true;
|
| + }
|
| +
|
| + // Check for a software backing store of the desired size.
|
| + *backing_store = BackingStoreManager::GetBackingStore(this, desired_size);
|
| + return !!*backing_store;
|
| +}
|
| +
|
| BackingStore* RenderWidgetHostImpl::GetBackingStore(bool force_create) {
|
| + if (!view_)
|
| + return NULL;
|
| +
|
| + // The view_size will be current_size_ for auto-sized views and otherwise the
|
| + // size of the view_. (For auto-sized views, current_size_ is updated during
|
| + // UpdateRect messages.)
|
| + gfx::Size view_size = current_size_;
|
| + if (!should_auto_resize_) {
|
| + // Get the desired size from the current view bounds.
|
| + gfx::Rect view_rect = view_->GetViewBounds();
|
| + if (view_rect.IsEmpty())
|
| + return NULL;
|
| + view_size = view_rect.size();
|
| + }
|
| +
|
| TRACE_EVENT2("renderer_host", "RenderWidgetHostImpl::GetBackingStore",
|
| - "width", base::IntToString(current_size_.width()),
|
| - "height", base::IntToString(current_size_.height()));
|
| + "width", base::IntToString(view_size.width()),
|
| + "height", base::IntToString(view_size.height()));
|
|
|
| // We should not be asked to paint while we are hidden. If we are hidden,
|
| // then it means that our consumer failed to call WasRestored. If we're not
|
| @@ -592,32 +623,58 @@ BackingStore* RenderWidgetHostImpl::GetBackingStore(bool force_create) {
|
| AutoReset<bool> auto_reset_in_get_backing_store(&in_get_backing_store_, true);
|
|
|
| // We might have a cached backing store that we can reuse!
|
| - BackingStore* backing_store =
|
| - BackingStoreManager::GetBackingStore(this, current_size_);
|
| - if (!force_create)
|
| + BackingStore* backing_store = NULL;
|
| + if (TryGetBackingStore(view_size, &backing_store) || !force_create)
|
| return backing_store;
|
|
|
| - // If we fail to find a backing store in the cache, send out a request
|
| - // to the renderer to paint the view if required.
|
| - if (!backing_store && !repaint_ack_pending_ && !resize_ack_pending_ &&
|
| - !view_being_painted_) {
|
| + // We do not have a suitable backing store in the cache, so send out a
|
| + // request to the renderer to paint the view if required.
|
| + if (!repaint_ack_pending_ && !resize_ack_pending_ && !view_being_painted_) {
|
| repaint_start_time_ = TimeTicks::Now();
|
| repaint_ack_pending_ = true;
|
| - Send(new ViewMsg_Repaint(routing_id_, current_size_));
|
| + Send(new ViewMsg_Repaint(routing_id_, view_size));
|
| }
|
|
|
| - // When we have asked the RenderWidget to resize, and we are still waiting on
|
| - // a response, block for a little while to see if we can't get a response
|
| - // before returning the old (incorrectly sized) backing store.
|
| - if (resize_ack_pending_ || !backing_store) {
|
| + TimeDelta max_delay = TimeDelta::FromMilliseconds(kPaintMsgTimeoutMS);
|
| + TimeTicks end_time = TimeTicks::Now() + max_delay;
|
| + do {
|
| + TRACE_EVENT0("renderer_host", "GetBackingStore::WaitForUpdate");
|
| +
|
| + // When we have asked the RenderWidget to resize, and we are still waiting
|
| + // on a response, block for a little while to see if we can't get a response
|
| + // before returning the old (incorrectly sized) backing store.
|
| IPC::Message msg;
|
| - TimeDelta max_delay = TimeDelta::FromMilliseconds(kPaintMsgTimeoutMS);
|
| - if (process_->WaitForUpdateMsg(routing_id_, max_delay, &msg)) {
|
| + if (process_->WaitForBackingStoreMsg(routing_id_, max_delay, &msg)) {
|
| OnMessageReceived(msg);
|
| - backing_store = BackingStoreManager::GetBackingStore(this, current_size_);
|
| +
|
| + // For auto-resized views, current_size_ determines the view_size and it
|
| + // may have changed during the handling of an UpdateRect message.
|
| + if (should_auto_resize_)
|
| + view_size = current_size_;
|
| +
|
| + // Break now if we got a backing store or accelerated surface of the
|
| + // correct size.
|
| + if (TryGetBackingStore(view_size, &backing_store) ||
|
| + abort_get_backing_store_) {
|
| + abort_get_backing_store_ = false;
|
| + return backing_store;
|
| + }
|
| + } else {
|
| + TRACE_EVENT0("renderer_host", "GetBackingStore::Timeout");
|
| + break;
|
| }
|
| - }
|
|
|
| + // Loop if we still have time left and haven't gotten a properly sized
|
| + // BackingStore yet. This is necessary to support the GPU path which
|
| + // typically has multiple frames pipelined -- we may need to skip one or two
|
| + // BackingStore messages to get to the latest.
|
| + max_delay = end_time - TimeTicks::Now();
|
| + } while (max_delay > TimeDelta::FromSeconds(0));
|
| +
|
| + // We have failed to get a backing store of view_size. Fall back on
|
| + // current_size_ to avoid a white flash while resizing slow pages.
|
| + if (view_size != current_size_)
|
| + TryGetBackingStore(current_size_, &backing_store);
|
| return backing_store;
|
| }
|
|
|
| @@ -1143,6 +1200,32 @@ void RenderWidgetHostImpl::OnMsgPaintAtSizeAck(int tag, const gfx::Size& size) {
|
| Details<std::pair<int, gfx::Size> >(&details));
|
| }
|
|
|
| +void RenderWidgetHostImpl::OnCompositorSurfaceBuffersSwapped(
|
| + int32 surface_id,
|
| + uint64 surface_handle,
|
| + int32 route_id,
|
| + int32 gpu_process_host_id) {
|
| + TRACE_EVENT0("renderer_host",
|
| + "RenderWidgetHostImpl::OnCompositorSurfaceBuffersSwapped");
|
| + if (!view_) {
|
| + RenderWidgetHostImpl::AcknowledgeSwapBuffers(route_id,
|
| + gpu_process_host_id);
|
| + return;
|
| + }
|
| + GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params gpu_params;
|
| + gpu_params.surface_id = surface_id;
|
| + gpu_params.surface_handle = surface_handle;
|
| + gpu_params.route_id = route_id;
|
| +#if defined(OS_MACOSX)
|
| + // Compositor window is always gfx::kNullPluginWindow.
|
| + // TODO(jbates) http://crbug.com/105344 This will be removed when there are no
|
| + // plugin windows.
|
| + gpu_params.window = gfx::kNullPluginWindow;
|
| +#endif
|
| + view_->AcceleratedSurfaceBuffersSwapped(gpu_params,
|
| + gpu_process_host_id);
|
| +}
|
| +
|
| void RenderWidgetHostImpl::OnMsgUpdateRect(
|
| const ViewHostMsg_UpdateRect_Params& params) {
|
| TRACE_EVENT0("renderer_host", "RenderWidgetHostImpl::OnMsgUpdateRect");
|
| @@ -1175,44 +1258,44 @@ void RenderWidgetHostImpl::OnMsgUpdateRect(
|
| DCHECK(!params.view_size.IsEmpty());
|
|
|
| bool was_async = false;
|
| - if (!is_accelerated_compositing_active_) {
|
| +
|
| + // If this is a GPU UpdateRect, params.bitmap is invalid and dib will be NULL.
|
| + TransportDIB* dib = process_->GetTransportDIB(params.bitmap);
|
| +
|
| + // If gpu process does painting, scroll_rect and copy_rects are always empty
|
| + // and backing store is never used.
|
| + if (dib) {
|
| DCHECK(!params.bitmap_rect.IsEmpty());
|
| const size_t size = params.bitmap_rect.height() *
|
| params.bitmap_rect.width() * 4;
|
| - TransportDIB* dib = process_->GetTransportDIB(params.bitmap);
|
| -
|
| - // If gpu process does painting, scroll_rect and copy_rects are always empty
|
| - // and backing store is never used.
|
| - if (dib) {
|
| - if (dib->size() < size) {
|
| - DLOG(WARNING) << "Transport DIB too small for given rectangle";
|
| - RecordAction(UserMetricsAction("BadMessageTerminate_RWH1"));
|
| - GetProcess()->ReceivedBadMessage();
|
| - } else {
|
| - UNSHIPPED_TRACE_EVENT_INSTANT2("test_latency", "UpdateRect",
|
| - "x+y", params.bitmap_rect.x() + params.bitmap_rect.y(),
|
| - "color", 0xffffff & *static_cast<uint32*>(dib->memory()));
|
| - UNSHIPPED_TRACE_EVENT_INSTANT1("test_latency", "UpdateRectWidth",
|
| - "width", params.bitmap_rect.width());
|
| -
|
| - // Scroll the backing store.
|
| - if (!params.scroll_rect.IsEmpty()) {
|
| - ScrollBackingStoreRect(params.dx, params.dy,
|
| - params.scroll_rect,
|
| - params.view_size);
|
| - }
|
| -
|
| - // Paint the backing store. This will update it with the
|
| - // renderer-supplied bits. The view will read out of the backing store
|
| - // later to actually draw to the screen.
|
| - was_async = PaintBackingStoreRect(
|
| - params.bitmap,
|
| - params.bitmap_rect,
|
| - params.copy_rects,
|
| - params.view_size,
|
| - base::Bind(&RenderWidgetHostImpl::DidUpdateBackingStore,
|
| - weak_factory_.GetWeakPtr(), params, paint_start));
|
| + if (dib->size() < size) {
|
| + DLOG(WARNING) << "Transport DIB too small for given rectangle";
|
| + RecordAction(UserMetricsAction("BadMessageTerminate_RWH1"));
|
| + GetProcess()->ReceivedBadMessage();
|
| + } else {
|
| + UNSHIPPED_TRACE_EVENT_INSTANT2("test_latency", "UpdateRect",
|
| + "x+y", params.bitmap_rect.x() + params.bitmap_rect.y(),
|
| + "color", 0xffffff & *static_cast<uint32*>(dib->memory()));
|
| + UNSHIPPED_TRACE_EVENT_INSTANT1("test_latency", "UpdateRectWidth",
|
| + "width", params.bitmap_rect.width());
|
| +
|
| + // Scroll the backing store.
|
| + if (!params.scroll_rect.IsEmpty()) {
|
| + ScrollBackingStoreRect(params.dx, params.dy,
|
| + params.scroll_rect,
|
| + params.view_size);
|
| }
|
| +
|
| + // Paint the backing store. This will update it with the
|
| + // renderer-supplied bits. The view will read out of the backing store
|
| + // later to actually draw to the screen.
|
| + was_async = PaintBackingStoreRect(
|
| + params.bitmap,
|
| + params.bitmap_rect,
|
| + params.copy_rects,
|
| + params.view_size,
|
| + base::Bind(&RenderWidgetHostImpl::DidUpdateBackingStore,
|
| + weak_factory_.GetWeakPtr(), params, paint_start));
|
| }
|
| }
|
|
|
| @@ -1239,7 +1322,8 @@ void RenderWidgetHostImpl::OnMsgUpdateRect(
|
| }
|
|
|
| void RenderWidgetHostImpl::OnMsgUpdateIsDelayed() {
|
| - // Nothing to do, this message was just to unblock the UI thread.
|
| + if (in_get_backing_store_)
|
| + abort_get_backing_store_ = true;
|
| }
|
|
|
| void RenderWidgetHostImpl::DidUpdateBackingStore(
|
| @@ -1286,11 +1370,8 @@ void RenderWidgetHostImpl::DidUpdateBackingStore(
|
| // If we got a resize ack, then perhaps we have another resize to send?
|
| bool is_resize_ack =
|
| ViewHostMsg_UpdateRect_Flags::is_resize_ack(params.flags);
|
| - if (is_resize_ack && view_) {
|
| - gfx::Rect view_bounds = view_->GetViewBounds();
|
| - if (current_size_ != view_bounds.size())
|
| - WasResized();
|
| - }
|
| + if (is_resize_ack)
|
| + WasResized();
|
|
|
| // Log the time delta for processing a paint message.
|
| TimeTicks now = TimeTicks::Now();
|
|
|