OLD | NEW |
---|---|
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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 "chrome/browser/renderer_host/render_widget_host.h" | 5 #include "chrome/browser/renderer_host/render_widget_host.h" |
6 | 6 |
7 #include "base/histogram.h" | 7 #include "base/histogram.h" |
8 #include "base/message_loop.h" | 8 #include "base/message_loop.h" |
9 #include "base/keyboard_codes.h" | 9 #include "base/keyboard_codes.h" |
10 #include "chrome/browser/renderer_host/backing_store.h" | 10 #include "chrome/browser/renderer_host/backing_store.h" |
11 #include "chrome/browser/renderer_host/render_process_host.h" | 11 #include "chrome/browser/renderer_host/render_process_host.h" |
12 #include "chrome/browser/renderer_host/render_widget_helper.h" | 12 #include "chrome/browser/renderer_host/render_widget_helper.h" |
13 #include "chrome/browser/renderer_host/render_widget_host_view.h" | 13 #include "chrome/browser/renderer_host/render_widget_host_view.h" |
14 #include "chrome/common/notification_service.h" | 14 #include "chrome/common/notification_service.h" |
15 #include "chrome/common/render_messages.h" | 15 #include "chrome/common/render_messages.h" |
16 #include "skia/ext/platform_canvas.h" | |
16 #include "views/view.h" | 17 #include "views/view.h" |
17 #include "webkit/glue/webcursor.h" | 18 #include "webkit/glue/webcursor.h" |
18 #include "webkit/glue/webtextdirection.h" | 19 #include "webkit/glue/webtextdirection.h" |
19 | 20 |
20 #if defined(OS_WIN) | 21 #if defined(OS_WIN) |
21 #include "base/gfx/gdi_util.h" | 22 #include "base/gfx/gdi_util.h" |
22 #include "chrome/app/chrome_dll_resource.h" | 23 #include "chrome/app/chrome_dll_resource.h" |
23 #endif // defined(OS_WIN) | 24 #endif // defined(OS_WIN) |
24 | 25 |
25 using base::Time; | 26 using base::Time; |
(...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
490 ViewHostMsg_PaintRect_Flags::is_repaint_ack(params.flags); | 491 ViewHostMsg_PaintRect_Flags::is_repaint_ack(params.flags); |
491 if (is_repaint_ack) { | 492 if (is_repaint_ack) { |
492 repaint_ack_pending_ = false; | 493 repaint_ack_pending_ = false; |
493 TimeDelta delta = TimeTicks::Now() - repaint_start_time_; | 494 TimeDelta delta = TimeTicks::Now() - repaint_start_time_; |
494 UMA_HISTOGRAM_TIMES("MPArch.RWH_RepaintDelta", delta); | 495 UMA_HISTOGRAM_TIMES("MPArch.RWH_RepaintDelta", delta); |
495 } | 496 } |
496 | 497 |
497 DCHECK(!params.bitmap_rect.IsEmpty()); | 498 DCHECK(!params.bitmap_rect.IsEmpty()); |
498 DCHECK(!params.view_size.IsEmpty()); | 499 DCHECK(!params.view_size.IsEmpty()); |
499 | 500 |
500 const size_t size = params.bitmap_rect.height() * | |
501 params.bitmap_rect.width() * 4; | |
502 TransportDIB* dib = process_->GetTransportDIB(params.bitmap); | 501 TransportDIB* dib = process_->GetTransportDIB(params.bitmap); |
503 if (dib) { | 502 if (dib) { |
503 const size_t size = params.bitmap_rect.height() * | |
504 skia::PlatformCanvas::StrideForWidth(params.bitmap_rect.width()); | |
504 if (dib->size() < size) { | 505 if (dib->size() < size) { |
505 DLOG(WARNING) << "Transport DIB too small for given rectangle"; | 506 DLOG(WARNING) << "Transport DIB too small for given rectangle"; |
506 process()->ReceivedBadMessage(ViewHostMsg_PaintRect__ID); | 507 process()->ReceivedBadMessage(ViewHostMsg_PaintRect__ID); |
507 } else { | 508 } else { |
508 // Paint the backing store. This will update it with the renderer-supplied | 509 // Paint the backing store. This will update it with the |
509 // bits. The view will read out of the backing store later to actually | 510 // renderer-supplied bits. The view will read out of the backing |
510 // draw to the screen. | 511 // store later to actually draw to the screen. |
511 PaintBackingStoreRect(dib, params.bitmap_rect, params.view_size); | 512 PaintBackingStoreRects(dib, params.bitmap_rect, params.paint_rects, |
513 params.view_size); | |
512 } | 514 } |
513 } | 515 } |
514 | 516 |
515 // ACK early so we can prefetch the next PaintRect if there is a next one. | 517 // ACK early so we can prefetch the next PaintRect if there is a next one. |
516 // This must be done AFTER we're done painting with the bitmap supplied by the | 518 // This must be done AFTER we're done painting with the bitmap supplied by the |
517 // renderer. This ACK is a signal to the renderer that the backing store can | 519 // renderer. This ACK is a signal to the renderer that the backing store can |
518 // be re-used, so the bitmap may be invalid after this call. | 520 // be re-used, so the bitmap may be invalid after this call. |
519 Send(new ViewMsg_PaintRect_ACK(routing_id_)); | 521 Send(new ViewMsg_PaintRect_ACK(routing_id_)); |
520 | 522 |
521 // We don't need to update the view if the view is hidden. We must do this | 523 // We don't need to update the view if the view is hidden. We must do this |
522 // early return after the ACK is sent, however, or the renderer will not send | 524 // early return after the ACK is sent, however, or the renderer will not send |
523 // is more data. | 525 // is more data. |
524 if (is_hidden_) | 526 if (is_hidden_) |
525 return; | 527 return; |
526 | 528 |
527 // Now paint the view. Watch out: it might be destroyed already. | 529 // Now paint the view. Watch out: it might be destroyed already. |
528 if (view_) { | 530 if (view_) { |
529 view_->MovePluginWindows(params.plugin_window_moves); | 531 view_->MovePluginWindows(params.plugin_window_moves); |
530 view_being_painted_ = true; | 532 view_being_painted_ = true; |
531 view_->DidPaintRect(params.bitmap_rect); | 533 if (params.paint_rects.empty()) { |
534 view_->DidPaintRect(params.bitmap_rect); | |
535 } else { | |
536 for (size_t i = 0; i < params.paint_rects.size(); ++i) | |
537 view_->DidPaintRect(params.paint_rects[i]); | |
538 } | |
532 view_being_painted_ = false; | 539 view_being_painted_ = false; |
533 } | 540 } |
534 | 541 |
535 if (paint_observer_.get()) | 542 if (paint_observer_.get()) |
536 paint_observer_->RenderWidgetHostDidPaint(this); | 543 paint_observer_->RenderWidgetHostDidPaint(this); |
537 | 544 |
538 // If we got a resize ack, then perhaps we have another resize to send? | 545 // If we got a resize ack, then perhaps we have another resize to send? |
539 if (is_resize_ack && view_) { | 546 if (is_resize_ack && view_) { |
540 gfx::Rect view_bounds = view_->GetViewBounds(); | 547 gfx::Rect view_bounds = view_->GetViewBounds(); |
541 if (current_size_.width() != view_bounds.width() || | 548 if (current_size_.width() != view_bounds.width() || |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
612 mouse_move_pending_ = false; | 619 mouse_move_pending_ = false; |
613 | 620 |
614 // now, we can send the next mouse move event | 621 // now, we can send the next mouse move event |
615 if (next_mouse_move_.get()) { | 622 if (next_mouse_move_.get()) { |
616 DCHECK(next_mouse_move_->type == WebInputEvent::MouseMove); | 623 DCHECK(next_mouse_move_->type == WebInputEvent::MouseMove); |
617 ForwardMouseEvent(*next_mouse_move_); | 624 ForwardMouseEvent(*next_mouse_move_); |
618 } | 625 } |
619 } | 626 } |
620 | 627 |
621 if (WebInputEvent::isKeyboardEventType(type)) { | 628 if (WebInputEvent::isKeyboardEventType(type)) { |
622 if (key_queue_.size() == 0) { | 629 if (key_queue_.empty()) { |
623 LOG(ERROR) << "Got a KeyEvent back from the renderer but we " | 630 LOG(ERROR) << "Got a KeyEvent back from the renderer but we " |
624 << "don't seem to have sent it to the renderer!"; | 631 << "don't seem to have sent it to the renderer!"; |
625 } else if (key_queue_.front().type != type) { | 632 } else if (key_queue_.front().type != type) { |
626 LOG(ERROR) << "We seem to have a different key type sent from " | 633 LOG(ERROR) << "We seem to have a different key type sent from " |
627 << "the renderer. (" << key_queue_.front().type << " vs. " | 634 << "the renderer. (" << key_queue_.front().type << " vs. " |
628 << type << "). Ignoring event."; | 635 << type << "). Ignoring event."; |
629 } else { | 636 } else { |
630 bool processed = false; | 637 bool processed = false; |
631 r = message.ReadBool(&iter, &processed); | 638 r = message.ReadBool(&iter, &processed); |
632 DCHECK(r); | 639 DCHECK(r); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
680 | 687 |
681 view_->ShowPopupWithItems(validated_params.bounds, | 688 view_->ShowPopupWithItems(validated_params.bounds, |
682 validated_params.item_height, | 689 validated_params.item_height, |
683 validated_params.selected_item, | 690 validated_params.selected_item, |
684 validated_params.popup_items); | 691 validated_params.popup_items); |
685 #else // OS_WIN || OS_LINUX | 692 #else // OS_WIN || OS_LINUX |
686 NOTREACHED(); | 693 NOTREACHED(); |
687 #endif | 694 #endif |
688 } | 695 } |
689 | 696 |
690 void RenderWidgetHost::PaintBackingStoreRect(TransportDIB* bitmap, | 697 static bool CoversArea(const std::vector<gfx::Rect>& rects, |
darin (slow to review)
2009/06/10 17:23:24
nit: please move helper functions to the top of th
MAD
2009/06/10 19:00:13
Done.
| |
691 const gfx::Rect& bitmap_rect, | 698 const gfx::Size& size) { |
692 const gfx::Size& view_size) { | 699 #ifndef NDEBUG |
700 // Make sure there are no overlapping rects. That would make the | |
701 // test below irrelevant. We only do it in the debug build since | |
702 // this case "should" be covered in the renderer. | |
703 gfx::Rect view_rect(size.width(), size.height()); | |
704 size_t last_index = rects.size() - 1; | |
705 for (size_t i = 0; i < last_index; ++i) { | |
706 DCHECK(view_rect.Contains(rects[i])); | |
707 for (size_t j = i + 1; i < rects.size(); ++i) | |
708 DCHECK(!rects[i].Intersects(rects[j])); | |
709 } | |
710 DCHECK(view_rect.Contains(rects[last_index])); | |
711 #endif | |
712 int target_area = size.height() * size.width(); | |
713 int covered_area = 0; | |
714 for (size_t i = 0; i < rects.size(); ++i) { | |
715 covered_area += rects[i].height() * rects[i].width(); | |
716 } | |
717 return covered_area < target_area; | |
718 } | |
719 | |
720 void RenderWidgetHost::PaintBackingStoreRects( | |
721 TransportDIB* bitmap, const gfx::Rect& bitmap_rect, | |
722 const std::vector<gfx::Rect>& paint_rects, | |
723 const gfx::Size& view_size) { | |
693 // The view may be destroyed already. | 724 // The view may be destroyed already. |
694 if (!view_) | 725 if (!view_) |
695 return; | 726 return; |
696 | 727 |
697 if (is_hidden_) { | 728 if (is_hidden_) { |
698 // Don't bother updating the backing store when we're hidden. Just mark it | 729 // Don't bother updating the backing store when we're hidden. Just mark it |
699 // as being totally invalid. This will cause a complete repaint when the | 730 // as being totally invalid. This will cause a complete repaint when the |
700 // view is restored. | 731 // view is restored. |
701 needs_repainting_on_restore_ = true; | 732 needs_repainting_on_restore_ = true; |
702 return; | 733 return; |
703 } | 734 } |
704 | 735 |
705 bool needs_full_paint = false; | 736 bool needs_full_paint = false; |
706 BackingStore* backing_store = | 737 base::ProcessHandle process_handle = process_->process().handle(); |
707 BackingStoreManager::PrepareBackingStore(this, view_size, | 738 if (paint_rects.empty()) { |
708 process_->process().handle(), | 739 BackingStore* backing_store = |
709 bitmap, bitmap_rect, | 740 BackingStoreManager::PrepareBackingStore(this, view_size, |
710 &needs_full_paint); | 741 process_handle, bitmap, bitmap_rect, bitmap_rect, |
711 DCHECK(backing_store != NULL); | 742 &needs_full_paint); |
743 DCHECK(backing_store != NULL); | |
744 } else { | |
745 bool checked_coverage = false; | |
746 // TODO(agl): Reduce the number of X server round trips on Linux. | |
747 for (size_t i = 0; i < paint_rects.size(); ++i) { | |
748 BackingStore* backing_store = | |
749 BackingStoreManager::PrepareBackingStore(this, view_size, | |
750 process_handle, bitmap, bitmap_rect, paint_rects[i], | |
751 &needs_full_paint); | |
752 DCHECK(backing_store != NULL); | |
753 if (needs_full_paint) { | |
754 // We should not need a full paint more than once for a given view size | |
755 DCHECK(!checked_coverage); | |
756 checked_coverage = true; | |
757 | |
758 // Before we ask for a full repaint, we check if we already have a | |
759 // full coverage of the view size in out list of paint_rects | |
760 if (CoversArea(paint_rects, view_size)) | |
761 break; | |
762 needs_full_paint = false; | |
763 } | |
764 } | |
765 } | |
766 | |
712 if (needs_full_paint) { | 767 if (needs_full_paint) { |
713 repaint_start_time_ = TimeTicks::Now(); | 768 repaint_start_time_ = TimeTicks::Now(); |
714 repaint_ack_pending_ = true; | 769 repaint_ack_pending_ = true; |
715 Send(new ViewMsg_Repaint(routing_id_, view_size)); | 770 Send(new ViewMsg_Repaint(routing_id_, view_size)); |
716 } | 771 } |
717 } | 772 } |
718 | 773 |
719 void RenderWidgetHost::ScrollBackingStoreRect(TransportDIB* bitmap, | 774 void RenderWidgetHost::ScrollBackingStoreRect(TransportDIB* bitmap, |
720 const gfx::Rect& bitmap_rect, | 775 const gfx::Rect& bitmap_rect, |
721 int dx, int dy, | 776 int dx, int dy, |
722 const gfx::Rect& clip_rect, | 777 const gfx::Rect& clip_rect, |
723 const gfx::Size& view_size) { | 778 const gfx::Size& view_size) { |
724 if (is_hidden_) { | 779 if (is_hidden_) { |
725 // Don't bother updating the backing store when we're hidden. Just mark it | 780 // Don't bother updating the backing store when we're hidden. Just mark it |
726 // as being totally invalid. This will cause a complete repaint when the | 781 // as being totally invalid. This will cause a complete repaint when the |
727 // view is restored. | 782 // view is restored. |
728 needs_repainting_on_restore_ = true; | 783 needs_repainting_on_restore_ = true; |
729 return; | 784 return; |
730 } | 785 } |
731 | 786 |
732 // TODO(darin): do we need to do something else if our backing store is not | 787 // TODO(darin): do we need to do something else if our backing store is not |
733 // the same size as the advertised view? maybe we just assume there is a | 788 // the same size as the advertised view? maybe we just assume there is a |
734 // full paint on its way? | 789 // full paint on its way? |
735 BackingStore* backing_store = BackingStoreManager::Lookup(this); | 790 BackingStore* backing_store = BackingStoreManager::Lookup(this); |
736 if (!backing_store || (backing_store->size() != view_size)) | 791 if (!backing_store || (backing_store->size() != view_size)) |
737 return; | 792 return; |
738 backing_store->ScrollRect(process_->process().handle(), bitmap, bitmap_rect, | 793 backing_store->ScrollRect(process_->process().handle(), bitmap, bitmap_rect, |
739 dx, dy, clip_rect, view_size); | 794 dx, dy, clip_rect, view_size); |
740 } | 795 } |
OLD | NEW |