Chromium Code Reviews| 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..d5d6121261d69190edefb79ea0a1fba87d86f915 100644 |
| --- a/content/browser/renderer_host/render_widget_host_impl.cc |
| +++ b/content/browser/renderer_host/render_widget_host_impl.cc |
| @@ -575,9 +575,18 @@ void RenderWidgetHostImpl::PaintAtSize(TransportDIB::Handle dib_handle, |
| } |
| BackingStore* RenderWidgetHostImpl::GetBackingStore(bool force_create) { |
| + if (!view_) |
| + return NULL; |
| + |
| + // Get the desired size from the current view bounds. |
| + gfx::Rect view_rect = view_->GetViewBounds(); |
| + if (view_rect.IsEmpty()) |
| + return NULL; |
| + gfx::Size 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 |
| @@ -591,9 +600,15 @@ BackingStore* RenderWidgetHostImpl::GetBackingStore(bool force_create) { |
| DCHECK(!in_get_backing_store_) << "GetBackingStore called recursively!"; |
| AutoReset<bool> auto_reset_in_get_backing_store(&in_get_backing_store_, true); |
| + // If there's an accelerated surface, return NULL now. The caller will need |
| + // to confirm whether there is an accelerated frame after GetBackingStore |
| + // returns. |
| + if (view_->HasAcceleratedSurface(view_size)) |
| + return NULL; |
| + |
| // We might have a cached backing store that we can reuse! |
| BackingStore* backing_store = |
| - BackingStoreManager::GetBackingStore(this, current_size_); |
| + BackingStoreManager::GetBackingStore(this, view_size); |
| if (!force_create) |
| return backing_store; |
| @@ -603,7 +618,7 @@ BackingStore* RenderWidgetHostImpl::GetBackingStore(bool force_create) { |
| !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 |
| @@ -612,12 +627,39 @@ BackingStore* RenderWidgetHostImpl::GetBackingStore(bool force_create) { |
| if (resize_ack_pending_ || !backing_store) { |
| IPC::Message msg; |
| TimeDelta max_delay = TimeDelta::FromMilliseconds(kPaintMsgTimeoutMS); |
| - if (process_->WaitForUpdateMsg(routing_id_, max_delay, &msg)) { |
| - OnMessageReceived(msg); |
| - backing_store = BackingStoreManager::GetBackingStore(this, current_size_); |
| - } |
| + TimeTicks end_time = TimeTicks::Now() + max_delay; |
| + do { |
| + TRACE_EVENT0("renderer_host", "GetBackingStore::WaitForUpdate"); |
| + |
| + view_->AboutToWaitForUpdateMsg(); |
| + if (process_->WaitForUpdateMsg(routing_id_, max_delay, &msg)) { |
| + OnMessageReceived(msg); |
| + backing_store = BackingStoreManager::GetBackingStore(this, view_size); |
| + // Break now if we got a backing store or accelerated surface of the |
| + // correct size. |
| + if (view_->HasAcceleratedSurface(view_size)) |
| + return NULL; |
| + backing_store = BackingStoreManager::GetBackingStore(this, view_size); |
|
piman
2012/04/18 20:02:00
Why doing this twice?
jbates
2012/04/18 23:01:58
Copy-paste error. Deleted the first instance.
|
| + if (backing_store) |
| + 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 |
| + // frame yet. This is necessary to support the GPU path which typically |
| + // has multiple frames pipelined -- we may need to skip one or two |
| + // UpdateRects to get to the latest. |
| + max_delay = end_time - TimeTicks::Now(); |
| + } while (max_delay > TimeDelta::FromSeconds(0)); |
| } |
| + // If we have still failed to get a backing store of view_size, fall back on |
| + // current_size_ to attempt to avoid a white flash while resizing slow pages. |
| + if (!backing_store) |
| + backing_store = BackingStoreManager::GetBackingStore(this, current_size_); |
| + |
| return backing_store; |
| } |
| @@ -1146,6 +1188,25 @@ void RenderWidgetHostImpl::OnMsgPaintAtSizeAck(int tag, const gfx::Size& size) { |
| void RenderWidgetHostImpl::OnMsgUpdateRect( |
| const ViewHostMsg_UpdateRect_Params& params) { |
| TRACE_EVENT0("renderer_host", "RenderWidgetHostImpl::OnMsgUpdateRect"); |
| + |
| + if (params.gpu_surface_id) { |
| + GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params gpu_params; |
| + gpu_params.surface_id = params.gpu_surface_id; |
| + gpu_params.surface_handle = params.gpu_surface_handle; |
| + gpu_params.route_id = params.gpu_route_id; |
| +#if defined(OS_MACOSX) |
| + // Compositor window is always gfx::kNullPluginWindow. |
| + // TODO(jbates) This will be removed when there are no plugin windows. |
| + gpu_params.window = gfx::kNullPluginWindow; |
| +#endif |
| + view_->AcceleratedSurfaceBuffersSwapped(gpu_params, |
| + params.gpu_process_host_id); |
| + // Nothing more to do, because this type of UpdateRect only contains |
| + // SwapBuffers state. The real UpdateRect will be sent later by the |
| + // renderer. |
| + return; |
| + } |
| + |
| TimeTicks paint_start = TimeTicks::Now(); |
| // Update our knowledge of the RenderWidget's size. |
| @@ -1175,44 +1236,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)); |
| } |
| } |