Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(179)

Side by Side Diff: content/browser/renderer_host/render_widget_host_view_mac.mm

Issue 25942002: Make software compositing work on Mac. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix includes Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698