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

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: Touch-ups 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 402 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698