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_view_mac.h" | 5 #include "content/browser/renderer_host/render_widget_host_view_mac.h" |
6 | 6 |
7 #import <objc/runtime.h> | 7 #import <objc/runtime.h> |
8 #include <QuartzCore/QuartzCore.h> | 8 #include <QuartzCore/QuartzCore.h> |
9 | 9 |
10 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
419 call_set_needs_display_in_rect_pending_(false), | 419 call_set_needs_display_in_rect_pending_(false), |
420 last_frame_was_accelerated_(false), | 420 last_frame_was_accelerated_(false), |
421 text_input_type_(ui::TEXT_INPUT_TYPE_NONE), | 421 text_input_type_(ui::TEXT_INPUT_TYPE_NONE), |
422 can_compose_inline_(true), | 422 can_compose_inline_(true), |
423 allow_overlapping_views_(false), | 423 allow_overlapping_views_(false), |
424 use_core_animation_(false), | 424 use_core_animation_(false), |
425 is_loading_(false), | 425 is_loading_(false), |
426 weak_factory_(this), | 426 weak_factory_(this), |
427 fullscreen_parent_host_view_(NULL), | 427 fullscreen_parent_host_view_(NULL), |
428 pending_swap_buffers_acks_weak_factory_(this), | 428 pending_swap_buffers_acks_weak_factory_(this), |
429 next_swap_ack_time_(base::Time::Now()) { | 429 next_swap_ack_time_(base::Time::Now()), |
430 software_frame_weak_ptr_factory_(this) { | |
431 software_frame_manager_.reset(new SoftwareFrameManager( | |
432 software_frame_weak_ptr_factory_.GetWeakPtr())); | |
430 // |cocoa_view_| owns us and we will be deleted when |cocoa_view_| | 433 // |cocoa_view_| owns us and we will be deleted when |cocoa_view_| |
431 // goes away. Since we autorelease it, our caller must put | 434 // goes away. Since we autorelease it, our caller must put |
432 // |GetNativeView()| into the view hierarchy right after calling us. | 435 // |GetNativeView()| into the view hierarchy right after calling us. |
433 cocoa_view_ = [[[RenderWidgetHostViewCocoa alloc] | 436 cocoa_view_ = [[[RenderWidgetHostViewCocoa alloc] |
434 initWithRenderWidgetHostViewMac:this] autorelease]; | 437 initWithRenderWidgetHostViewMac:this] autorelease]; |
435 | 438 |
436 if (GetCoreAnimationStatus() == CORE_ANIMATION_ENABLED_ALWAYS) { | 439 if (GetCoreAnimationStatus() == CORE_ANIMATION_ENABLED_ALWAYS) { |
437 EnableCoreAnimation(); | 440 EnableCoreAnimation(); |
438 } | 441 } |
439 | 442 |
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
725 return render_widget_host_; | 728 return render_widget_host_; |
726 } | 729 } |
727 | 730 |
728 void RenderWidgetHostViewMac::WasShown() { | 731 void RenderWidgetHostViewMac::WasShown() { |
729 if (!render_widget_host_->is_hidden()) | 732 if (!render_widget_host_->is_hidden()) |
730 return; | 733 return; |
731 | 734 |
732 if (web_contents_switch_paint_time_.is_null()) | 735 if (web_contents_switch_paint_time_.is_null()) |
733 web_contents_switch_paint_time_ = base::TimeTicks::Now(); | 736 web_contents_switch_paint_time_ = base::TimeTicks::Now(); |
734 render_widget_host_->WasShown(); | 737 render_widget_host_->WasShown(); |
738 software_frame_manager_->SetVisibility(true); | |
735 | 739 |
736 // We're messing with the window, so do this to ensure no flashes. | 740 // We're messing with the window, so do this to ensure no flashes. |
737 if (!use_core_animation_) | 741 if (!use_core_animation_) |
738 [[cocoa_view_ window] disableScreenUpdatesUntilFlush]; | 742 [[cocoa_view_ window] disableScreenUpdatesUntilFlush]; |
739 | 743 |
740 [compositing_iosurface_layer_ setNeedsDisplay]; | 744 [compositing_iosurface_layer_ setNeedsDisplay]; |
741 } | 745 } |
742 | 746 |
743 void RenderWidgetHostViewMac::WasHidden() { | 747 void RenderWidgetHostViewMac::WasHidden() { |
744 if (render_widget_host_->is_hidden()) | 748 if (render_widget_host_->is_hidden()) |
745 return; | 749 return; |
746 | 750 |
747 // Send ACKs for any pending SwapBuffers (if any) since we won't be displaying | 751 // Send ACKs for any pending SwapBuffers (if any) since we won't be displaying |
748 // them and the GPU process is waiting. | 752 // them and the GPU process is waiting. |
749 AckPendingSwapBuffers(); | 753 AckPendingSwapBuffers(); |
750 | 754 |
751 // If we have a renderer, then inform it that we are being hidden so it can | 755 // If we have a renderer, then inform it that we are being hidden so it can |
752 // reduce its resource utilization. | 756 // reduce its resource utilization. |
753 render_widget_host_->WasHidden(); | 757 render_widget_host_->WasHidden(); |
758 software_frame_manager_->SetVisibility(false); | |
754 | 759 |
755 // There can be a transparent flash as this view is removed and the next is | 760 // There can be a transparent flash as this view is removed and the next is |
756 // added, because of OSX windowing races between displaying the contents of | 761 // added, because of OSX windowing races between displaying the contents of |
757 // the NSView and its corresponding OpenGL context. | 762 // the NSView and its corresponding OpenGL context. |
758 // disableScreenUpdatesUntilFlush prevents the transparent flash by avoiding | 763 // disableScreenUpdatesUntilFlush prevents the transparent flash by avoiding |
759 // screen updates until the next tab draws. | 764 // screen updates until the next tab draws. |
760 if (!use_core_animation_) | 765 if (!use_core_animation_) |
761 [[cocoa_view_ window] disableScreenUpdatesUntilFlush]; | 766 [[cocoa_view_ window] disableScreenUpdatesUntilFlush]; |
762 | 767 |
763 web_contents_switch_paint_time_ = base::TimeTicks(); | 768 web_contents_switch_paint_time_ = base::TimeTicks(); |
(...skipping 879 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1643 if (compositing_iosurface_) | 1648 if (compositing_iosurface_) |
1644 compositing_iosurface_->UnrefIOSurface(); | 1649 compositing_iosurface_->UnrefIOSurface(); |
1645 } | 1650 } |
1646 | 1651 |
1647 void RenderWidgetHostViewMac::AcceleratedSurfaceRelease() { | 1652 void RenderWidgetHostViewMac::AcceleratedSurfaceRelease() { |
1648 DestroyCompositedIOSurfaceAndLayer(kDestroyContext); | 1653 DestroyCompositedIOSurfaceAndLayer(kDestroyContext); |
1649 } | 1654 } |
1650 | 1655 |
1651 bool RenderWidgetHostViewMac::HasAcceleratedSurface( | 1656 bool RenderWidgetHostViewMac::HasAcceleratedSurface( |
1652 const gfx::Size& desired_size) { | 1657 const gfx::Size& desired_size) { |
1653 return last_frame_was_accelerated_ && | 1658 if (last_frame_was_accelerated_) { |
1654 compositing_iosurface_ && | 1659 return compositing_iosurface_ && |
1655 compositing_iosurface_->HasIOSurface() && | 1660 compositing_iosurface_->HasIOSurface() && |
1656 (desired_size.IsEmpty() || | 1661 (desired_size.IsEmpty() || |
1657 compositing_iosurface_->dip_io_surface_size() == desired_size); | 1662 compositing_iosurface_->dip_io_surface_size() == desired_size); |
1663 } else { | |
1664 return (software_frame_manager_->HasCurrentFrame() && | |
1665 (desired_size.IsEmpty() || | |
1666 software_frame_manager_->GetCurrentFrameSizeInDIP() == | |
1667 desired_size)); | |
1668 } | |
1669 return false; | |
1658 } | 1670 } |
1659 | 1671 |
1660 void RenderWidgetHostViewMac::AboutToWaitForBackingStoreMsg() { | 1672 void RenderWidgetHostViewMac::AboutToWaitForBackingStoreMsg() { |
1661 AckPendingSwapBuffers(); | 1673 AckPendingSwapBuffers(); |
1662 } | 1674 } |
1663 | 1675 |
1676 void RenderWidgetHostViewMac::OnSwapCompositorFrame( | |
1677 uint32 output_surface_id, scoped_ptr<cc::CompositorFrame> frame) { | |
1678 // Only software compositor frames are accepted. | |
1679 if (!frame->software_frame_data) { | |
1680 render_widget_host_->GetProcess()->ReceivedBadMessage(); | |
piman
2013/10/22 22:32:48
That's quite extreme :) Do we really need to kill
ccameron
2013/10/23 01:05:58
I'd rather blow up the renderer than silently acce
piman
2013/10/23 23:41:40
So, you're not accepting input, you're just droppi
| |
1681 return; | |
1682 } | |
1683 | |
1684 GotSoftwareFrame(); | |
1685 if (!software_frame_manager_->SwapToNewFrame( | |
1686 output_surface_id, | |
1687 frame->software_frame_data.get(), | |
1688 frame->metadata.device_scale_factor, | |
1689 render_widget_host_->GetProcess()->GetHandle())) { | |
1690 render_widget_host_->GetProcess()->ReceivedBadMessage(); | |
1691 return; | |
1692 } | |
1693 software_frame_manager_->SwapToNewFrameComplete( | |
1694 !render_widget_host_->is_hidden()); | |
1695 | |
1696 [cocoa_view_ setNeedsDisplay:YES]; | |
1697 } | |
1698 | |
1664 void RenderWidgetHostViewMac::OnAcceleratedCompositingStateChange() { | 1699 void RenderWidgetHostViewMac::OnAcceleratedCompositingStateChange() { |
1665 } | 1700 } |
1666 | 1701 |
1667 void RenderWidgetHostViewMac::GetScreenInfo(WebKit::WebScreenInfo* results) { | 1702 void RenderWidgetHostViewMac::GetScreenInfo(WebKit::WebScreenInfo* results) { |
1668 *results = GetWebScreenInfo(GetNativeView()); | 1703 *results = GetWebScreenInfo(GetNativeView()); |
1669 } | 1704 } |
1670 | 1705 |
1671 gfx::Rect RenderWidgetHostViewMac::GetBoundsInRootWindow() { | 1706 gfx::Rect RenderWidgetHostViewMac::GetBoundsInRootWindow() { |
1672 // TODO(shess): In case of !window, the view has been removed from | 1707 // TODO(shess): In case of !window, the view has been removed from |
1673 // the view hierarchy because the tab isn't main. Could retrieve | 1708 // the view hierarchy because the tab isn't main. Could retrieve |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1734 [cocoa_view_ gotUnhandledWheelEvent]; | 1769 [cocoa_view_ gotUnhandledWheelEvent]; |
1735 } | 1770 } |
1736 | 1771 |
1737 bool RenderWidgetHostViewMac::Send(IPC::Message* message) { | 1772 bool RenderWidgetHostViewMac::Send(IPC::Message* message) { |
1738 if (render_widget_host_) | 1773 if (render_widget_host_) |
1739 return render_widget_host_->Send(message); | 1774 return render_widget_host_->Send(message); |
1740 delete message; | 1775 delete message; |
1741 return false; | 1776 return false; |
1742 } | 1777 } |
1743 | 1778 |
1779 void RenderWidgetHostViewMac::SoftwareFrameWasFreed( | |
1780 uint32 output_surface_id, unsigned frame_id) { | |
1781 cc::CompositorFrameAck ack; | |
1782 ack.last_software_frame_id = frame_id; | |
1783 RenderWidgetHostImpl::SendReclaimCompositorResources( | |
1784 render_widget_host_->GetRoutingID(), | |
1785 output_surface_id, | |
1786 render_widget_host_->GetProcess()->GetID(), | |
1787 ack); | |
1788 } | |
1789 | |
1790 void RenderWidgetHostViewMac::CurrentSoftwareFrameWasEvicted() { | |
1791 } | |
1744 | 1792 |
1745 void RenderWidgetHostViewMac::ShutdownHost() { | 1793 void RenderWidgetHostViewMac::ShutdownHost() { |
1746 weak_factory_.InvalidateWeakPtrs(); | 1794 weak_factory_.InvalidateWeakPtrs(); |
1747 render_widget_host_->Shutdown(); | 1795 render_widget_host_->Shutdown(); |
1748 // Do not touch any members at this point, |this| has been deleted. | 1796 // Do not touch any members at this point, |this| has been deleted. |
1749 } | 1797 } |
1750 | 1798 |
1751 void RenderWidgetHostViewMac::GotAcceleratedFrame() { | 1799 void RenderWidgetHostViewMac::GotAcceleratedFrame() { |
1752 // Update the scale factor of the layer to match the scale factor of the | 1800 // Update the scale factor of the layer to match the scale factor of the |
1753 // IOSurface. | 1801 // IOSurface. |
1754 [compositing_iosurface_layer_ updateScaleFactor]; | 1802 [compositing_iosurface_layer_ updateScaleFactor]; |
1755 | 1803 |
1756 if (!last_frame_was_accelerated_) { | 1804 if (!last_frame_was_accelerated_) { |
1757 last_frame_was_accelerated_ = true; | 1805 last_frame_was_accelerated_ = true; |
1758 | 1806 |
1759 if (!use_core_animation_) { | 1807 if (!use_core_animation_) { |
1760 // Need to wipe the software view with transparency to expose the GL | 1808 // Need to wipe the software view with transparency to expose the GL |
1761 // underlay. Invalidate the whole window to do that. | 1809 // underlay. Invalidate the whole window to do that. |
1762 [cocoa_view_ setNeedsDisplay:YES]; | 1810 [cocoa_view_ setNeedsDisplay:YES]; |
1763 } | 1811 } |
1764 | 1812 |
1765 // Delete software backingstore. | 1813 // Delete software backingstore. |
1766 BackingStoreManager::RemoveBackingStore(render_widget_host_); | 1814 BackingStoreManager::RemoveBackingStore(render_widget_host_); |
1815 software_frame_manager_->DiscardCurrentFrame(); | |
1767 } | 1816 } |
1768 } | 1817 } |
1769 | 1818 |
1770 void RenderWidgetHostViewMac::GotSoftwareFrame() { | 1819 void RenderWidgetHostViewMac::GotSoftwareFrame() { |
1771 if (last_frame_was_accelerated_) { | 1820 if (last_frame_was_accelerated_) { |
1772 last_frame_was_accelerated_ = false; | 1821 last_frame_was_accelerated_ = false; |
1773 | 1822 |
1774 AckPendingSwapBuffers(); | 1823 AckPendingSwapBuffers(); |
1775 | 1824 |
1776 // If overlapping views are allowed, then don't unbind the context | 1825 // If overlapping views are allowed, then don't unbind the context |
(...skipping 934 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2711 CGContextRef context = static_cast<CGContextRef>( | 2760 CGContextRef context = static_cast<CGContextRef>( |
2712 [[NSGraphicsContext currentContext] graphicsPort]); | 2761 [[NSGraphicsContext currentContext] graphicsPort]); |
2713 [self drawBackingStore:backingStore | 2762 [self drawBackingStore:backingStore |
2714 dirtyRect:NSRectToCGRect(dirtyRect) | 2763 dirtyRect:NSRectToCGRect(dirtyRect) |
2715 inContext:context]; | 2764 inContext:context]; |
2716 } | 2765 } |
2717 | 2766 |
2718 - (void)drawBackingStore:(BackingStoreMac*)backingStore | 2767 - (void)drawBackingStore:(BackingStoreMac*)backingStore |
2719 dirtyRect:(CGRect)dirtyRect | 2768 dirtyRect:(CGRect)dirtyRect |
2720 inContext:(CGContextRef)context { | 2769 inContext:(CGContextRef)context { |
2721 if (backingStore) { | 2770 content::SoftwareFrameManager* software_frame_manager = |
2771 renderWidgetHostView_->software_frame_manager_.get(); | |
2772 // There should never be both a legacy software and software composited | |
2773 // frame. | |
2774 DCHECK(!backingStore || !software_frame_manager->HasCurrentFrame()); | |
2775 | |
2776 if (backingStore || software_frame_manager->HasCurrentFrame()) { | |
2722 // Note: All coordinates are in view units, not pixels. | 2777 // Note: All coordinates are in view units, not pixels. |
2723 gfx::Rect bitmapRect(0, 0, | 2778 gfx::Rect bitmapRect( |
2724 backingStore->size().width(), | 2779 software_frame_manager->HasCurrentFrame() ? |
2725 backingStore->size().height()); | 2780 software_frame_manager->GetCurrentFrameSizeInDIP() : |
2781 backingStore->size()); | |
2726 | 2782 |
2727 // Specify the proper y offset to ensure that the view is rooted to the | 2783 // Specify the proper y offset to ensure that the view is rooted to the |
2728 // upper left corner. This can be negative, if the window was resized | 2784 // upper left corner. This can be negative, if the window was resized |
2729 // smaller and the renderer hasn't yet repainted. | 2785 // smaller and the renderer hasn't yet repainted. |
2730 int yOffset = NSHeight([self bounds]) - backingStore->size().height(); | 2786 int yOffset = NSHeight([self bounds]) - bitmapRect.height(); |
2731 | 2787 |
2732 NSRect nsDirtyRect = NSRectFromCGRect(dirtyRect); | 2788 NSRect nsDirtyRect = NSRectFromCGRect(dirtyRect); |
2733 const gfx::Rect damagedRect([self flipNSRectToRect:nsDirtyRect]); | 2789 const gfx::Rect damagedRect([self flipNSRectToRect:nsDirtyRect]); |
2734 | 2790 |
2735 gfx::Rect paintRect = gfx::IntersectRects(bitmapRect, damagedRect); | 2791 gfx::Rect paintRect = gfx::IntersectRects(bitmapRect, damagedRect); |
2736 if (!paintRect.IsEmpty()) { | 2792 if (!paintRect.IsEmpty()) { |
2737 // if we have a CGLayer, draw that into the window | 2793 if (software_frame_manager->HasCurrentFrame()) { |
2738 if (backingStore->cg_layer()) { | 2794 // If a software compositor framebuffer is present, draw using that. |
2795 gfx::Size sizeInPixels = | |
2796 software_frame_manager->GetCurrentFrameSizeInPixels(); | |
2797 base::ScopedCFTypeRef<CGDataProviderRef> dataProvider( | |
2798 CGDataProviderCreateWithData( | |
2799 NULL, | |
2800 software_frame_manager->GetCurrentFramePixels(), | |
2801 4 * sizeInPixels.width() * sizeInPixels.height(), | |
2802 NULL)); | |
2803 base::ScopedCFTypeRef<CGImageRef> image( | |
2804 CGImageCreate( | |
2805 sizeInPixels.width(), | |
2806 sizeInPixels.height(), | |
2807 8, | |
2808 32, | |
2809 4 * sizeInPixels.width(), | |
2810 base::mac::GetSystemColorSpace(), | |
2811 kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host, | |
2812 dataProvider, | |
2813 NULL, | |
2814 false, | |
2815 kCGRenderingIntentDefault)); | |
2816 CGRect imageRect = bitmapRect.ToCGRect(); | |
2817 imageRect.origin.y = yOffset; | |
2818 CGContextDrawImage(context, imageRect, image); | |
2819 } else if (backingStore->cg_layer()) { | |
2820 // If we have a CGLayer, draw that into the window | |
2739 // TODO: add clipping to dirtyRect if it improves drawing performance. | 2821 // TODO: add clipping to dirtyRect if it improves drawing performance. |
2740 CGContextDrawLayerAtPoint(context, CGPointMake(0.0, yOffset), | 2822 CGContextDrawLayerAtPoint(context, CGPointMake(0.0, yOffset), |
2741 backingStore->cg_layer()); | 2823 backingStore->cg_layer()); |
2742 } else { | 2824 } else { |
2743 // if we haven't created a layer yet, draw the cached bitmap into | 2825 // If we haven't created a layer yet, draw the cached bitmap into |
2744 // the window. The CGLayer will be created the next time the renderer | 2826 // the window. The CGLayer will be created the next time the renderer |
2745 // paints. | 2827 // paints. |
2746 base::ScopedCFTypeRef<CGImageRef> image( | 2828 base::ScopedCFTypeRef<CGImageRef> image( |
2747 CGBitmapContextCreateImage(backingStore->cg_bitmap())); | 2829 CGBitmapContextCreateImage(backingStore->cg_bitmap())); |
2748 CGRect imageRect = bitmapRect.ToCGRect(); | 2830 CGRect imageRect = bitmapRect.ToCGRect(); |
2749 imageRect.origin.y = yOffset; | 2831 imageRect.origin.y = yOffset; |
2750 CGContextDrawImage(context, imageRect, image); | 2832 CGContextDrawImage(context, imageRect, image); |
2751 } | 2833 } |
2752 } | 2834 } |
2753 | 2835 |
(...skipping 1089 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3843 return YES; | 3925 return YES; |
3844 } | 3926 } |
3845 | 3927 |
3846 - (BOOL)isOpaque { | 3928 - (BOOL)isOpaque { |
3847 if (renderWidgetHostView_->use_core_animation_) | 3929 if (renderWidgetHostView_->use_core_animation_) |
3848 return YES; | 3930 return YES; |
3849 return [super isOpaque]; | 3931 return [super isOpaque]; |
3850 } | 3932 } |
3851 | 3933 |
3852 @end | 3934 @end |
OLD | NEW |