Chromium Code Reviews| 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 |