OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/renderer_host/render_widget_host_impl.h" | 5 #include "content/browser/renderer_host/render_widget_host_impl.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/auto_reset.h" | 9 #include "base/auto_reset.h" |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 557 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
568 const gfx::Size& page_size, | 568 const gfx::Size& page_size, |
569 const gfx::Size& desired_size) { | 569 const gfx::Size& desired_size) { |
570 // Ask the renderer to create a bitmap regardless of whether it's | 570 // Ask the renderer to create a bitmap regardless of whether it's |
571 // hidden, being resized, redrawn, etc. It resizes the web widget | 571 // hidden, being resized, redrawn, etc. It resizes the web widget |
572 // to the page_size and then scales it to the desired_size. | 572 // to the page_size and then scales it to the desired_size. |
573 Send(new ViewMsg_PaintAtSize(routing_id_, dib_handle, tag, | 573 Send(new ViewMsg_PaintAtSize(routing_id_, dib_handle, tag, |
574 page_size, desired_size)); | 574 page_size, desired_size)); |
575 } | 575 } |
576 | 576 |
577 BackingStore* RenderWidgetHostImpl::GetBackingStore(bool force_create) { | 577 BackingStore* RenderWidgetHostImpl::GetBackingStore(bool force_create) { |
578 if (!view_) | |
579 return NULL; | |
580 | |
581 // Get the desired size from the current view bounds. | |
582 gfx::Rect view_rect = view_->GetViewBounds(); | |
583 if (view_rect.IsEmpty()) | |
584 return NULL; | |
585 gfx::Size view_size = view_rect.size(); | |
586 | |
578 TRACE_EVENT2("renderer_host", "RenderWidgetHostImpl::GetBackingStore", | 587 TRACE_EVENT2("renderer_host", "RenderWidgetHostImpl::GetBackingStore", |
579 "width", base::IntToString(current_size_.width()), | 588 "width", base::IntToString(view_size.width()), |
580 "height", base::IntToString(current_size_.height())); | 589 "height", base::IntToString(view_size.height())); |
581 | 590 |
582 // We should not be asked to paint while we are hidden. If we are hidden, | 591 // We should not be asked to paint while we are hidden. If we are hidden, |
583 // then it means that our consumer failed to call WasRestored. If we're not | 592 // then it means that our consumer failed to call WasRestored. If we're not |
584 // force creating the backing store, it's OK since we can feel free to give | 593 // force creating the backing store, it's OK since we can feel free to give |
585 // out our cached one if we have it. | 594 // out our cached one if we have it. |
586 DCHECK(!is_hidden_ || !force_create) << | 595 DCHECK(!is_hidden_ || !force_create) << |
587 "GetBackingStore called while hidden!"; | 596 "GetBackingStore called while hidden!"; |
588 | 597 |
589 // We should never be called recursively; this can theoretically lead to | 598 // We should never be called recursively; this can theoretically lead to |
590 // infinite recursion and almost certainly leads to lower performance. | 599 // infinite recursion and almost certainly leads to lower performance. |
591 DCHECK(!in_get_backing_store_) << "GetBackingStore called recursively!"; | 600 DCHECK(!in_get_backing_store_) << "GetBackingStore called recursively!"; |
592 AutoReset<bool> auto_reset_in_get_backing_store(&in_get_backing_store_, true); | 601 AutoReset<bool> auto_reset_in_get_backing_store(&in_get_backing_store_, true); |
593 | 602 |
603 // If there's an accelerated surface, return NULL now. The caller will need | |
604 // to confirm whether there is an accelerated frame after GetBackingStore | |
605 // returns. | |
606 if (view_->HasAcceleratedSurface(view_size)) | |
607 return NULL; | |
608 | |
594 // We might have a cached backing store that we can reuse! | 609 // We might have a cached backing store that we can reuse! |
595 BackingStore* backing_store = | 610 BackingStore* backing_store = |
596 BackingStoreManager::GetBackingStore(this, current_size_); | 611 BackingStoreManager::GetBackingStore(this, view_size); |
597 if (!force_create) | 612 if (!force_create) |
598 return backing_store; | 613 return backing_store; |
599 | 614 |
600 // If we fail to find a backing store in the cache, send out a request | 615 // If we fail to find a backing store in the cache, send out a request |
601 // to the renderer to paint the view if required. | 616 // to the renderer to paint the view if required. |
602 if (!backing_store && !repaint_ack_pending_ && !resize_ack_pending_ && | 617 if (!backing_store && !repaint_ack_pending_ && !resize_ack_pending_ && |
603 !view_being_painted_) { | 618 !view_being_painted_) { |
604 repaint_start_time_ = TimeTicks::Now(); | 619 repaint_start_time_ = TimeTicks::Now(); |
605 repaint_ack_pending_ = true; | 620 repaint_ack_pending_ = true; |
606 Send(new ViewMsg_Repaint(routing_id_, current_size_)); | 621 Send(new ViewMsg_Repaint(routing_id_, view_size)); |
607 } | 622 } |
608 | 623 |
609 // When we have asked the RenderWidget to resize, and we are still waiting on | 624 // When we have asked the RenderWidget to resize, and we are still waiting on |
610 // a response, block for a little while to see if we can't get a response | 625 // a response, block for a little while to see if we can't get a response |
611 // before returning the old (incorrectly sized) backing store. | 626 // before returning the old (incorrectly sized) backing store. |
612 if (resize_ack_pending_ || !backing_store) { | 627 if (resize_ack_pending_ || !backing_store) { |
613 IPC::Message msg; | 628 IPC::Message msg; |
614 TimeDelta max_delay = TimeDelta::FromMilliseconds(kPaintMsgTimeoutMS); | 629 TimeDelta max_delay = TimeDelta::FromMilliseconds(kPaintMsgTimeoutMS); |
615 if (process_->WaitForUpdateMsg(routing_id_, max_delay, &msg)) { | 630 TimeTicks end_time = TimeTicks::Now() + max_delay; |
616 OnMessageReceived(msg); | 631 do { |
617 backing_store = BackingStoreManager::GetBackingStore(this, current_size_); | 632 TRACE_EVENT0("renderer_host", "GetBackingStore::WaitForUpdate"); |
618 } | 633 |
634 view_->AboutToWaitForUpdateMsg(); | |
635 if (process_->WaitForUpdateMsg(routing_id_, max_delay, &msg)) { | |
636 OnMessageReceived(msg); | |
637 backing_store = BackingStoreManager::GetBackingStore(this, view_size); | |
638 // Break now if we got a backing store or accelerated surface of the | |
639 // correct size. | |
640 if (view_->HasAcceleratedSurface(view_size)) | |
641 return NULL; | |
642 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.
| |
643 if (backing_store) | |
644 return backing_store; | |
645 } else { | |
646 TRACE_EVENT0("renderer_host", "GetBackingStore::Timeout"); | |
647 break; | |
648 } | |
649 | |
650 // Loop if we still have time left and haven't gotten a properly sized | |
651 // frame yet. This is necessary to support the GPU path which typically | |
652 // has multiple frames pipelined -- we may need to skip one or two | |
653 // UpdateRects to get to the latest. | |
654 max_delay = end_time - TimeTicks::Now(); | |
655 } while (max_delay > TimeDelta::FromSeconds(0)); | |
619 } | 656 } |
620 | 657 |
658 // If we have still failed to get a backing store of view_size, fall back on | |
659 // current_size_ to attempt to avoid a white flash while resizing slow pages. | |
660 if (!backing_store) | |
661 backing_store = BackingStoreManager::GetBackingStore(this, current_size_); | |
662 | |
621 return backing_store; | 663 return backing_store; |
622 } | 664 } |
623 | 665 |
624 BackingStore* RenderWidgetHostImpl::AllocBackingStore(const gfx::Size& size) { | 666 BackingStore* RenderWidgetHostImpl::AllocBackingStore(const gfx::Size& size) { |
625 if (!view_) | 667 if (!view_) |
626 return NULL; | 668 return NULL; |
627 return view_->AllocBackingStore(size); | 669 return view_->AllocBackingStore(size); |
628 } | 670 } |
629 | 671 |
630 void RenderWidgetHostImpl::DonePaintingToBackingStore() { | 672 void RenderWidgetHostImpl::DonePaintingToBackingStore() { |
(...skipping 508 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1139 std::pair<int, gfx::Size> details = std::make_pair(tag, size); | 1181 std::pair<int, gfx::Size> details = std::make_pair(tag, size); |
1140 NotificationService::current()->Notify( | 1182 NotificationService::current()->Notify( |
1141 NOTIFICATION_RENDER_WIDGET_HOST_DID_RECEIVE_PAINT_AT_SIZE_ACK, | 1183 NOTIFICATION_RENDER_WIDGET_HOST_DID_RECEIVE_PAINT_AT_SIZE_ACK, |
1142 Source<RenderWidgetHost>(this), | 1184 Source<RenderWidgetHost>(this), |
1143 Details<std::pair<int, gfx::Size> >(&details)); | 1185 Details<std::pair<int, gfx::Size> >(&details)); |
1144 } | 1186 } |
1145 | 1187 |
1146 void RenderWidgetHostImpl::OnMsgUpdateRect( | 1188 void RenderWidgetHostImpl::OnMsgUpdateRect( |
1147 const ViewHostMsg_UpdateRect_Params& params) { | 1189 const ViewHostMsg_UpdateRect_Params& params) { |
1148 TRACE_EVENT0("renderer_host", "RenderWidgetHostImpl::OnMsgUpdateRect"); | 1190 TRACE_EVENT0("renderer_host", "RenderWidgetHostImpl::OnMsgUpdateRect"); |
1191 | |
1192 if (params.gpu_surface_id) { | |
1193 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params gpu_params; | |
1194 gpu_params.surface_id = params.gpu_surface_id; | |
1195 gpu_params.surface_handle = params.gpu_surface_handle; | |
1196 gpu_params.route_id = params.gpu_route_id; | |
1197 #if defined(OS_MACOSX) | |
1198 // Compositor window is always gfx::kNullPluginWindow. | |
1199 // TODO(jbates) This will be removed when there are no plugin windows. | |
1200 gpu_params.window = gfx::kNullPluginWindow; | |
1201 #endif | |
1202 view_->AcceleratedSurfaceBuffersSwapped(gpu_params, | |
1203 params.gpu_process_host_id); | |
1204 // Nothing more to do, because this type of UpdateRect only contains | |
1205 // SwapBuffers state. The real UpdateRect will be sent later by the | |
1206 // renderer. | |
1207 return; | |
1208 } | |
1209 | |
1149 TimeTicks paint_start = TimeTicks::Now(); | 1210 TimeTicks paint_start = TimeTicks::Now(); |
1150 | 1211 |
1151 // Update our knowledge of the RenderWidget's size. | 1212 // Update our knowledge of the RenderWidget's size. |
1152 current_size_ = params.view_size; | 1213 current_size_ = params.view_size; |
1153 // Update our knowledge of the RenderWidget's scroll offset. | 1214 // Update our knowledge of the RenderWidget's scroll offset. |
1154 last_scroll_offset_ = params.scroll_offset; | 1215 last_scroll_offset_ = params.scroll_offset; |
1155 | 1216 |
1156 bool is_resize_ack = | 1217 bool is_resize_ack = |
1157 ViewHostMsg_UpdateRect_Flags::is_resize_ack(params.flags); | 1218 ViewHostMsg_UpdateRect_Flags::is_resize_ack(params.flags); |
1158 | 1219 |
1159 // resize_ack_pending_ needs to be cleared before we call DidPaintRect, since | 1220 // resize_ack_pending_ needs to be cleared before we call DidPaintRect, since |
1160 // that will end up reaching GetBackingStore. | 1221 // that will end up reaching GetBackingStore. |
1161 if (is_resize_ack) { | 1222 if (is_resize_ack) { |
1162 DCHECK(resize_ack_pending_); | 1223 DCHECK(resize_ack_pending_); |
1163 resize_ack_pending_ = false; | 1224 resize_ack_pending_ = false; |
1164 in_flight_size_.SetSize(0, 0); | 1225 in_flight_size_.SetSize(0, 0); |
1165 } | 1226 } |
1166 | 1227 |
1167 bool is_repaint_ack = | 1228 bool is_repaint_ack = |
1168 ViewHostMsg_UpdateRect_Flags::is_repaint_ack(params.flags); | 1229 ViewHostMsg_UpdateRect_Flags::is_repaint_ack(params.flags); |
1169 if (is_repaint_ack) { | 1230 if (is_repaint_ack) { |
1170 repaint_ack_pending_ = false; | 1231 repaint_ack_pending_ = false; |
1171 TimeDelta delta = TimeTicks::Now() - repaint_start_time_; | 1232 TimeDelta delta = TimeTicks::Now() - repaint_start_time_; |
1172 UMA_HISTOGRAM_TIMES("MPArch.RWH_RepaintDelta", delta); | 1233 UMA_HISTOGRAM_TIMES("MPArch.RWH_RepaintDelta", delta); |
1173 } | 1234 } |
1174 | 1235 |
1175 DCHECK(!params.view_size.IsEmpty()); | 1236 DCHECK(!params.view_size.IsEmpty()); |
1176 | 1237 |
1177 bool was_async = false; | 1238 bool was_async = false; |
1178 if (!is_accelerated_compositing_active_) { | 1239 |
1240 // If this is a GPU UpdateRect, params.bitmap is invalid and dib will be NULL. | |
1241 TransportDIB* dib = process_->GetTransportDIB(params.bitmap); | |
1242 | |
1243 // If gpu process does painting, scroll_rect and copy_rects are always empty | |
1244 // and backing store is never used. | |
1245 if (dib) { | |
1179 DCHECK(!params.bitmap_rect.IsEmpty()); | 1246 DCHECK(!params.bitmap_rect.IsEmpty()); |
1180 const size_t size = params.bitmap_rect.height() * | 1247 const size_t size = params.bitmap_rect.height() * |
1181 params.bitmap_rect.width() * 4; | 1248 params.bitmap_rect.width() * 4; |
1182 TransportDIB* dib = process_->GetTransportDIB(params.bitmap); | 1249 if (dib->size() < size) { |
1250 DLOG(WARNING) << "Transport DIB too small for given rectangle"; | |
1251 RecordAction(UserMetricsAction("BadMessageTerminate_RWH1")); | |
1252 GetProcess()->ReceivedBadMessage(); | |
1253 } else { | |
1254 UNSHIPPED_TRACE_EVENT_INSTANT2("test_latency", "UpdateRect", | |
1255 "x+y", params.bitmap_rect.x() + params.bitmap_rect.y(), | |
1256 "color", 0xffffff & *static_cast<uint32*>(dib->memory())); | |
1257 UNSHIPPED_TRACE_EVENT_INSTANT1("test_latency", "UpdateRectWidth", | |
1258 "width", params.bitmap_rect.width()); | |
1183 | 1259 |
1184 // If gpu process does painting, scroll_rect and copy_rects are always empty | 1260 // Scroll the backing store. |
1185 // and backing store is never used. | 1261 if (!params.scroll_rect.IsEmpty()) { |
1186 if (dib) { | 1262 ScrollBackingStoreRect(params.dx, params.dy, |
1187 if (dib->size() < size) { | 1263 params.scroll_rect, |
1188 DLOG(WARNING) << "Transport DIB too small for given rectangle"; | 1264 params.view_size); |
1189 RecordAction(UserMetricsAction("BadMessageTerminate_RWH1")); | 1265 } |
1190 GetProcess()->ReceivedBadMessage(); | |
1191 } else { | |
1192 UNSHIPPED_TRACE_EVENT_INSTANT2("test_latency", "UpdateRect", | |
1193 "x+y", params.bitmap_rect.x() + params.bitmap_rect.y(), | |
1194 "color", 0xffffff & *static_cast<uint32*>(dib->memory())); | |
1195 UNSHIPPED_TRACE_EVENT_INSTANT1("test_latency", "UpdateRectWidth", | |
1196 "width", params.bitmap_rect.width()); | |
1197 | 1266 |
1198 // Scroll the backing store. | 1267 // Paint the backing store. This will update it with the |
1199 if (!params.scroll_rect.IsEmpty()) { | 1268 // renderer-supplied bits. The view will read out of the backing store |
1200 ScrollBackingStoreRect(params.dx, params.dy, | 1269 // later to actually draw to the screen. |
1201 params.scroll_rect, | 1270 was_async = PaintBackingStoreRect( |
1202 params.view_size); | 1271 params.bitmap, |
1203 } | 1272 params.bitmap_rect, |
1204 | 1273 params.copy_rects, |
1205 // Paint the backing store. This will update it with the | 1274 params.view_size, |
1206 // renderer-supplied bits. The view will read out of the backing store | 1275 base::Bind(&RenderWidgetHostImpl::DidUpdateBackingStore, |
1207 // later to actually draw to the screen. | 1276 weak_factory_.GetWeakPtr(), params, paint_start)); |
1208 was_async = PaintBackingStoreRect( | |
1209 params.bitmap, | |
1210 params.bitmap_rect, | |
1211 params.copy_rects, | |
1212 params.view_size, | |
1213 base::Bind(&RenderWidgetHostImpl::DidUpdateBackingStore, | |
1214 weak_factory_.GetWeakPtr(), params, paint_start)); | |
1215 } | |
1216 } | 1277 } |
1217 } | 1278 } |
1218 | 1279 |
1219 if (!was_async) { | 1280 if (!was_async) { |
1220 DidUpdateBackingStore(params, paint_start); | 1281 DidUpdateBackingStore(params, paint_start); |
1221 } | 1282 } |
1222 | 1283 |
1223 if (should_auto_resize_) { | 1284 if (should_auto_resize_) { |
1224 bool post_callback = new_auto_size_.IsEmpty(); | 1285 bool post_callback = new_auto_size_.IsEmpty(); |
1225 new_auto_size_ = params.view_size; | 1286 new_auto_size_ = params.view_size; |
(...skipping 500 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1726 // indicate that no callback is in progress (i.e. without this line | 1787 // indicate that no callback is in progress (i.e. without this line |
1727 // DelayedAutoResized will not get called again). | 1788 // DelayedAutoResized will not get called again). |
1728 new_auto_size_.SetSize(0, 0); | 1789 new_auto_size_.SetSize(0, 0); |
1729 if (!should_auto_resize_) | 1790 if (!should_auto_resize_) |
1730 return; | 1791 return; |
1731 | 1792 |
1732 OnRenderAutoResized(new_size); | 1793 OnRenderAutoResized(new_size); |
1733 } | 1794 } |
1734 | 1795 |
1735 } // namespace content | 1796 } // namespace content |
OLD | NEW |