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

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

Powered by Google App Engine
This is Rietveld 408576698