| 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 402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 413 /////////////////////////////////////////////////////////////////////////////// | 413 /////////////////////////////////////////////////////////////////////////////// |
| 414 // RenderWidgetHostViewMac, public: | 414 // RenderWidgetHostViewMac, public: |
| 415 | 415 |
| 416 RenderWidgetHostViewMac::RenderWidgetHostViewMac(RenderWidgetHost* widget) | 416 RenderWidgetHostViewMac::RenderWidgetHostViewMac(RenderWidgetHost* widget) |
| 417 : render_widget_host_(RenderWidgetHostImpl::From(widget)), | 417 : render_widget_host_(RenderWidgetHostImpl::From(widget)), |
| 418 about_to_validate_and_paint_(false), | 418 about_to_validate_and_paint_(false), |
| 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 software_framebuffer_(new SoftwareFramebuffer( |
| 424 this, RenderWidgetHostImpl::From(widget))), |
| 423 allow_overlapping_views_(false), | 425 allow_overlapping_views_(false), |
| 424 use_core_animation_(false), | 426 use_core_animation_(false), |
| 425 is_loading_(false), | 427 is_loading_(false), |
| 426 is_hidden_(false), | 428 is_hidden_(false), |
| 427 weak_factory_(this), | 429 weak_factory_(this), |
| 428 fullscreen_parent_host_view_(NULL), | 430 fullscreen_parent_host_view_(NULL), |
| 429 pending_swap_buffers_acks_weak_factory_(this), | 431 pending_swap_buffers_acks_weak_factory_(this), |
| 430 next_swap_ack_time_(base::Time::Now()) { | 432 next_swap_ack_time_(base::Time::Now()) { |
| 431 // |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_| |
| 432 // goes away. Since we autorelease it, our caller must put | 434 // goes away. Since we autorelease it, our caller must put |
| (...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 727 } | 729 } |
| 728 | 730 |
| 729 void RenderWidgetHostViewMac::WasShown() { | 731 void RenderWidgetHostViewMac::WasShown() { |
| 730 if (!is_hidden_) | 732 if (!is_hidden_) |
| 731 return; | 733 return; |
| 732 | 734 |
| 733 if (web_contents_switch_paint_time_.is_null()) | 735 if (web_contents_switch_paint_time_.is_null()) |
| 734 web_contents_switch_paint_time_ = base::TimeTicks::Now(); | 736 web_contents_switch_paint_time_ = base::TimeTicks::Now(); |
| 735 is_hidden_ = false; | 737 is_hidden_ = false; |
| 736 render_widget_host_->WasShown(); | 738 render_widget_host_->WasShown(); |
| 739 software_framebuffer_->WasShown(); |
| 737 | 740 |
| 738 // We're messing with the window, so do this to ensure no flashes. | 741 // We're messing with the window, so do this to ensure no flashes. |
| 739 if (!use_core_animation_) | 742 if (!use_core_animation_) |
| 740 [[cocoa_view_ window] disableScreenUpdatesUntilFlush]; | 743 [[cocoa_view_ window] disableScreenUpdatesUntilFlush]; |
| 741 | 744 |
| 742 [compositing_iosurface_layer_ setNeedsDisplay]; | 745 [compositing_iosurface_layer_ setNeedsDisplay]; |
| 743 } | 746 } |
| 744 | 747 |
| 745 void RenderWidgetHostViewMac::WasHidden() { | 748 void RenderWidgetHostViewMac::WasHidden() { |
| 746 if (is_hidden_) | 749 if (is_hidden_) |
| 747 return; | 750 return; |
| 748 | 751 |
| 749 // Send ACKs for any pending SwapBuffers (if any) since we won't be displaying | 752 // Send ACKs for any pending SwapBuffers (if any) since we won't be displaying |
| 750 // them and the GPU process is waiting. | 753 // them and the GPU process is waiting. |
| 751 AckPendingSwapBuffers(); | 754 AckPendingSwapBuffers(); |
| 752 | 755 |
| 753 // If we receive any more paint messages while we are hidden, we want to | 756 // If we receive any more paint messages while we are hidden, we want to |
| 754 // ignore them so we don't re-allocate the backing store. We will paint | 757 // ignore them so we don't re-allocate the backing store. We will paint |
| 755 // everything again when we become selected again. | 758 // everything again when we become selected again. |
| 756 is_hidden_ = true; | 759 is_hidden_ = true; |
| 757 | 760 |
| 758 // If we have a renderer, then inform it that we are being hidden so it can | 761 // If we have a renderer, then inform it that we are being hidden so it can |
| 759 // reduce its resource utilization. | 762 // reduce its resource utilization. |
| 760 render_widget_host_->WasHidden(); | 763 render_widget_host_->WasHidden(); |
| 764 software_framebuffer_->WasHidden(); |
| 761 | 765 |
| 762 // There can be a transparent flash as this view is removed and the next is | 766 // There can be a transparent flash as this view is removed and the next is |
| 763 // added, because of OSX windowing races between displaying the contents of | 767 // added, because of OSX windowing races between displaying the contents of |
| 764 // the NSView and its corresponding OpenGL context. | 768 // the NSView and its corresponding OpenGL context. |
| 765 // disableScreenUpdatesUntilFlush prevents the transparent flash by avoiding | 769 // disableScreenUpdatesUntilFlush prevents the transparent flash by avoiding |
| 766 // screen updates until the next tab draws. | 770 // screen updates until the next tab draws. |
| 767 if (!use_core_animation_) | 771 if (!use_core_animation_) |
| 768 [[cocoa_view_ window] disableScreenUpdatesUntilFlush]; | 772 [[cocoa_view_ window] disableScreenUpdatesUntilFlush]; |
| 769 | 773 |
| 770 web_contents_switch_paint_time_ = base::TimeTicks(); | 774 web_contents_switch_paint_time_ = base::TimeTicks(); |
| (...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1214 | 1218 |
| 1215 void RenderWidgetHostViewMac::BeginFrameSubscription( | 1219 void RenderWidgetHostViewMac::BeginFrameSubscription( |
| 1216 scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) { | 1220 scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) { |
| 1217 frame_subscriber_ = subscriber.Pass(); | 1221 frame_subscriber_ = subscriber.Pass(); |
| 1218 } | 1222 } |
| 1219 | 1223 |
| 1220 void RenderWidgetHostViewMac::EndFrameSubscription() { | 1224 void RenderWidgetHostViewMac::EndFrameSubscription() { |
| 1221 frame_subscriber_.reset(); | 1225 frame_subscriber_.reset(); |
| 1222 } | 1226 } |
| 1223 | 1227 |
| 1228 void RenderWidgetHostViewMac::OnSwapCompositorFrame( |
| 1229 uint32 output_surface_id, scoped_ptr<cc::CompositorFrame> frame) { |
| 1230 // Only software compositor frames are accepted. |
| 1231 if (!frame->software_frame_data) { |
| 1232 render_widget_host_->GetProcess()->ReceivedBadMessage(); |
| 1233 return; |
| 1234 } |
| 1235 |
| 1236 GotSoftwareFrame(); |
| 1237 |
| 1238 software_framebuffer_->SwapToNewFrame( |
| 1239 output_surface_id, |
| 1240 frame->software_frame_data.get(), |
| 1241 frame->metadata.device_scale_factor); |
| 1242 |
| 1243 [cocoa_view_ setNeedsDisplay:YES]; |
| 1244 } |
| 1245 |
| 1224 // Sets whether or not to accept first responder status. | 1246 // Sets whether or not to accept first responder status. |
| 1225 void RenderWidgetHostViewMac::SetTakesFocusOnlyOnMouseDown(bool flag) { | 1247 void RenderWidgetHostViewMac::SetTakesFocusOnlyOnMouseDown(bool flag) { |
| 1226 [cocoa_view_ setTakesFocusOnlyOnMouseDown:flag]; | 1248 [cocoa_view_ setTakesFocusOnlyOnMouseDown:flag]; |
| 1227 } | 1249 } |
| 1228 | 1250 |
| 1229 void RenderWidgetHostViewMac::ForwardMouseEvent(const WebMouseEvent& event) { | 1251 void RenderWidgetHostViewMac::ForwardMouseEvent(const WebMouseEvent& event) { |
| 1230 if (render_widget_host_) | 1252 if (render_widget_host_) |
| 1231 render_widget_host_->ForwardMouseEvent(event); | 1253 render_widget_host_->ForwardMouseEvent(event); |
| 1232 | 1254 |
| 1233 if (event.type == WebInputEvent::MouseLeave) { | 1255 if (event.type == WebInputEvent::MouseLeave) { |
| (...skipping 416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1650 if (compositing_iosurface_) | 1672 if (compositing_iosurface_) |
| 1651 compositing_iosurface_->UnrefIOSurface(); | 1673 compositing_iosurface_->UnrefIOSurface(); |
| 1652 } | 1674 } |
| 1653 | 1675 |
| 1654 void RenderWidgetHostViewMac::AcceleratedSurfaceRelease() { | 1676 void RenderWidgetHostViewMac::AcceleratedSurfaceRelease() { |
| 1655 DestroyCompositedIOSurfaceAndLayer(kDestroyContext); | 1677 DestroyCompositedIOSurfaceAndLayer(kDestroyContext); |
| 1656 } | 1678 } |
| 1657 | 1679 |
| 1658 bool RenderWidgetHostViewMac::HasAcceleratedSurface( | 1680 bool RenderWidgetHostViewMac::HasAcceleratedSurface( |
| 1659 const gfx::Size& desired_size) { | 1681 const gfx::Size& desired_size) { |
| 1660 return last_frame_was_accelerated_ && | 1682 if (last_frame_was_accelerated_) { |
| 1661 compositing_iosurface_ && | 1683 return (compositing_iosurface_ && |
| 1662 compositing_iosurface_->HasIOSurface() && | 1684 compositing_iosurface_->HasIOSurface() && |
| 1663 (desired_size.IsEmpty() || | 1685 (desired_size.IsEmpty() || |
| 1664 compositing_iosurface_->dip_io_surface_size() == desired_size); | 1686 compositing_iosurface_->dip_io_surface_size() == desired_size)); |
| 1687 } else { |
| 1688 return (software_framebuffer_->HasCurrentFrame() && |
| 1689 (desired_size.IsEmpty() || |
| 1690 software_framebuffer_->GetCurrentFrameSizeInDIP() == |
| 1691 desired_size)); |
| 1692 } |
| 1693 return false; |
| 1665 } | 1694 } |
| 1666 | 1695 |
| 1667 void RenderWidgetHostViewMac::AboutToWaitForBackingStoreMsg() { | 1696 void RenderWidgetHostViewMac::AboutToWaitForBackingStoreMsg() { |
| 1668 AckPendingSwapBuffers(); | 1697 AckPendingSwapBuffers(); |
| 1669 } | 1698 } |
| 1670 | 1699 |
| 1671 void RenderWidgetHostViewMac::OnAcceleratedCompositingStateChange() { | 1700 void RenderWidgetHostViewMac::OnAcceleratedCompositingStateChange() { |
| 1672 } | 1701 } |
| 1673 | 1702 |
| 1674 void RenderWidgetHostViewMac::GetScreenInfo(WebKit::WebScreenInfo* results) { | 1703 void RenderWidgetHostViewMac::GetScreenInfo(WebKit::WebScreenInfo* results) { |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1764 last_frame_was_accelerated_ = true; | 1793 last_frame_was_accelerated_ = true; |
| 1765 | 1794 |
| 1766 if (!use_core_animation_) { | 1795 if (!use_core_animation_) { |
| 1767 // Need to wipe the software view with transparency to expose the GL | 1796 // Need to wipe the software view with transparency to expose the GL |
| 1768 // underlay. Invalidate the whole window to do that. | 1797 // underlay. Invalidate the whole window to do that. |
| 1769 [cocoa_view_ setNeedsDisplay:YES]; | 1798 [cocoa_view_ setNeedsDisplay:YES]; |
| 1770 } | 1799 } |
| 1771 | 1800 |
| 1772 // Delete software backingstore. | 1801 // Delete software backingstore. |
| 1773 BackingStoreManager::RemoveBackingStore(render_widget_host_); | 1802 BackingStoreManager::RemoveBackingStore(render_widget_host_); |
| 1803 |
| 1804 // Delete the software compositing frame if one exists. |
| 1805 software_framebuffer_->DiscardCurrentFrame(); |
| 1774 } | 1806 } |
| 1775 } | 1807 } |
| 1776 | 1808 |
| 1777 void RenderWidgetHostViewMac::GotSoftwareFrame() { | 1809 void RenderWidgetHostViewMac::GotSoftwareFrame() { |
| 1778 if (last_frame_was_accelerated_) { | 1810 if (last_frame_was_accelerated_) { |
| 1779 last_frame_was_accelerated_ = false; | 1811 last_frame_was_accelerated_ = false; |
| 1780 | 1812 |
| 1781 AckPendingSwapBuffers(); | 1813 AckPendingSwapBuffers(); |
| 1782 | 1814 |
| 1783 // If overlapping views are allowed, then don't unbind the context | 1815 // If overlapping views are allowed, then don't unbind the context |
| (...skipping 933 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2717 CGContextRef context = static_cast<CGContextRef>( | 2749 CGContextRef context = static_cast<CGContextRef>( |
| 2718 [[NSGraphicsContext currentContext] graphicsPort]); | 2750 [[NSGraphicsContext currentContext] graphicsPort]); |
| 2719 [self drawBackingStore:backingStore | 2751 [self drawBackingStore:backingStore |
| 2720 dirtyRect:NSRectToCGRect(dirtyRect) | 2752 dirtyRect:NSRectToCGRect(dirtyRect) |
| 2721 inContext:context]; | 2753 inContext:context]; |
| 2722 } | 2754 } |
| 2723 | 2755 |
| 2724 - (void)drawBackingStore:(BackingStoreMac*)backingStore | 2756 - (void)drawBackingStore:(BackingStoreMac*)backingStore |
| 2725 dirtyRect:(CGRect)dirtyRect | 2757 dirtyRect:(CGRect)dirtyRect |
| 2726 inContext:(CGContextRef)context { | 2758 inContext:(CGContextRef)context { |
| 2727 if (backingStore) { | 2759 content::SoftwareFramebuffer* software_framebuffer = |
| 2760 renderWidgetHostView_->software_framebuffer_->HasCurrentFrame() ? |
| 2761 renderWidgetHostView_->software_framebuffer_.get() : NULL; |
| 2762 DCHECK(!backingStore || !software_framebuffer); |
| 2763 |
| 2764 if (backingStore || software_framebuffer) { |
| 2728 // Note: All coordinates are in view units, not pixels. | 2765 // Note: All coordinates are in view units, not pixels. |
| 2729 gfx::Rect bitmapRect(0, 0, | 2766 gfx::Rect bitmapRect(software_framebuffer ? |
| 2730 backingStore->size().width(), | 2767 software_framebuffer->GetCurrentFrameSizeInDIP() : |
| 2731 backingStore->size().height()); | 2768 backingStore->size()); |
| 2732 | 2769 |
| 2733 // Specify the proper y offset to ensure that the view is rooted to the | 2770 // Specify the proper y offset to ensure that the view is rooted to the |
| 2734 // upper left corner. This can be negative, if the window was resized | 2771 // upper left corner. This can be negative, if the window was resized |
| 2735 // smaller and the renderer hasn't yet repainted. | 2772 // smaller and the renderer hasn't yet repainted. |
| 2736 int yOffset = NSHeight([self bounds]) - backingStore->size().height(); | 2773 int yOffset = NSHeight([self bounds]) - bitmapRect.height(); |
| 2737 | 2774 |
| 2738 NSRect nsDirtyRect = NSRectFromCGRect(dirtyRect); | 2775 NSRect nsDirtyRect = NSRectFromCGRect(dirtyRect); |
| 2739 const gfx::Rect damagedRect([self flipNSRectToRect:nsDirtyRect]); | 2776 const gfx::Rect damagedRect([self flipNSRectToRect:nsDirtyRect]); |
| 2740 | 2777 |
| 2741 gfx::Rect paintRect = gfx::IntersectRects(bitmapRect, damagedRect); | 2778 gfx::Rect paintRect = gfx::IntersectRects(bitmapRect, damagedRect); |
| 2742 if (!paintRect.IsEmpty()) { | 2779 if (!paintRect.IsEmpty()) { |
| 2743 // if we have a CGLayer, draw that into the window | 2780 if (software_framebuffer) { |
| 2744 if (backingStore->cg_layer()) { | 2781 // If a software compositor framebuffer is present, draw using that. |
| 2782 gfx::Size sizeInPixels = |
| 2783 software_framebuffer->GetCurrentFrameSizeInPixels(); |
| 2784 |
| 2785 base::ScopedCFTypeRef<CGDataProviderRef> dataProvider( |
| 2786 CGDataProviderCreateWithData( |
| 2787 NULL, |
| 2788 software_framebuffer->GetCurrentFramePixels(), |
| 2789 4 * sizeInPixels.width() * sizeInPixels.height(), |
| 2790 NULL)); |
| 2791 |
| 2792 base::ScopedCFTypeRef<CGImageRef> image( |
| 2793 CGImageCreate( |
| 2794 sizeInPixels.width(), |
| 2795 sizeInPixels.height(), |
| 2796 8, |
| 2797 32, |
| 2798 4 * sizeInPixels.width(), |
| 2799 base::mac::GetSystemColorSpace(), |
| 2800 kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host, |
| 2801 dataProvider, |
| 2802 NULL, |
| 2803 false, |
| 2804 kCGRenderingIntentDefault)); |
| 2805 |
| 2806 CGRect imageRect = bitmapRect.ToCGRect(); |
| 2807 imageRect.origin.y = yOffset; |
| 2808 CGContextDrawImage(context, imageRect, image); |
| 2809 } else if (backingStore->cg_layer()) { |
| 2810 // If we have a CGLayer, draw that into the window |
| 2745 // TODO: add clipping to dirtyRect if it improves drawing performance. | 2811 // TODO: add clipping to dirtyRect if it improves drawing performance. |
| 2746 CGContextDrawLayerAtPoint(context, CGPointMake(0.0, yOffset), | 2812 CGContextDrawLayerAtPoint(context, CGPointMake(0.0, yOffset), |
| 2747 backingStore->cg_layer()); | 2813 backingStore->cg_layer()); |
| 2748 } else { | 2814 } else { |
| 2749 // if we haven't created a layer yet, draw the cached bitmap into | 2815 // If we haven't created a layer yet, draw the cached bitmap into |
| 2750 // the window. The CGLayer will be created the next time the renderer | 2816 // the window. The CGLayer will be created the next time the renderer |
| 2751 // paints. | 2817 // paints. |
| 2752 base::ScopedCFTypeRef<CGImageRef> image( | 2818 base::ScopedCFTypeRef<CGImageRef> image( |
| 2753 CGBitmapContextCreateImage(backingStore->cg_bitmap())); | 2819 CGBitmapContextCreateImage(backingStore->cg_bitmap())); |
| 2754 CGRect imageRect = bitmapRect.ToCGRect(); | 2820 CGRect imageRect = bitmapRect.ToCGRect(); |
| 2755 imageRect.origin.y = yOffset; | 2821 imageRect.origin.y = yOffset; |
| 2756 CGContextDrawImage(context, imageRect, image); | 2822 CGContextDrawImage(context, imageRect, image); |
| 2757 } | 2823 } |
| 2758 } | 2824 } |
| 2759 | 2825 |
| (...skipping 1088 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3848 return YES; | 3914 return YES; |
| 3849 } | 3915 } |
| 3850 | 3916 |
| 3851 - (BOOL)isOpaque { | 3917 - (BOOL)isOpaque { |
| 3852 if (renderWidgetHostView_->use_core_animation_) | 3918 if (renderWidgetHostView_->use_core_animation_) |
| 3853 return YES; | 3919 return YES; |
| 3854 return [super isOpaque]; | 3920 return [super isOpaque]; |
| 3855 } | 3921 } |
| 3856 | 3922 |
| 3857 @end | 3923 @end |
| OLD | NEW |