Index: content/browser/renderer_host/render_widget_host_view_mac.mm |
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm |
index 4a09adea7a0732db392cba490957133a53a5dec4..155a2cfb2d7c748a3b11535244f3f6a234c447be 100644 |
--- a/content/browser/renderer_host/render_widget_host_view_mac.mm |
+++ b/content/browser/renderer_host/render_widget_host_view_mac.mm |
@@ -24,6 +24,7 @@ |
#include "content/browser/plugin_process_host.h" |
#import "content/browser/renderer_host/accelerated_plugin_view_mac.h" |
#include "content/browser/renderer_host/backing_store_mac.h" |
+#include "content/browser/renderer_host/backing_store_manager.h" |
#include "content/browser/renderer_host/compositing_iosurface_mac.h" |
#include "content/browser/renderer_host/render_process_host_impl.h" |
#include "content/browser/renderer_host/render_view_host_impl.h" |
@@ -263,8 +264,7 @@ RenderWidgetHostViewMac::RenderWidgetHostViewMac(RenderWidgetHost* widget) |
can_compose_inline_(true), |
is_loading_(false), |
is_hidden_(false), |
- weak_factory_(this), |
- compositing_surface_(gfx::kNullPluginWindow) { |
+ weak_factory_(this) { |
// |cocoa_view_| owns us and we will be deleted when |cocoa_view_| |
// goes away. Since we autorelease it, our caller must put |
// |GetNativeView()| into the view hierarchy right after calling us. |
@@ -372,10 +372,6 @@ void RenderWidgetHostViewMac::WasHidden() { |
// everything again when we become selected again. |
is_hidden_ = true; |
- // Send ACKs for any pending SwapBuffers (if any) since we won't be displaying |
- // them and the GPU process is waiting. |
- AckPendingCompositorSwapBuffers(); |
- |
// If we have a renderer, then inform it that we are being hidden so it can |
// reduce its resource utilization. |
render_widget_host_->WasHidden(); |
@@ -613,7 +609,7 @@ void RenderWidgetHostViewMac::ImeCompositionRangeChanged( |
void RenderWidgetHostViewMac::DidUpdateBackingStore( |
const gfx::Rect& scroll_rect, int scroll_dx, int scroll_dy, |
const std::vector<gfx::Rect>& copy_rects) { |
- last_frame_was_accelerated_ = false; |
+ GotSoftwareFrame(); |
if (!is_hidden_) { |
std::vector<gfx::Rect> rects(copy_rects); |
@@ -683,9 +679,6 @@ void RenderWidgetHostViewMac::Destroy() { |
} |
} |
- // Ack pending swaps (if any). |
- AckPendingCompositorSwapBuffers(); |
- |
// We've been told to destroy. |
[cocoa_view_ retain]; |
[cocoa_view_ removeFromSuperview]; |
@@ -953,34 +946,22 @@ void RenderWidgetHostViewMac::AcceleratedSurfaceSetTransportDIB( |
transport_dib); |
} |
-void RenderWidgetHostViewMac::CompositorSwapBuffers(uint64 surface_handle, |
- int32 route_id, |
- int32 gpu_host_id) { |
- pending_swap_buffers_acks_.push_back(std::make_pair(route_id, gpu_host_id)); |
- if (!compositing_iosurface_.get() && !is_hidden_) { |
+void RenderWidgetHostViewMac::CompositorSwapBuffers(uint64 surface_handle) { |
+ if (is_hidden_) |
+ return; |
+ |
+ if (!compositing_iosurface_.get()) |
compositing_iosurface_.reset(CompositingIOSurfaceMac::Create()); |
- } |
- if (compositing_iosurface_.get() && !is_hidden_) { |
- last_frame_was_accelerated_ = true; |
- compositing_iosurface_->SetIOSurface(surface_handle); |
- [cocoa_view_ setNeedsDisplay:YES]; |
- } else { |
- AckPendingCompositorSwapBuffers(); |
- } |
-} |
+ if (!compositing_iosurface_.get()) |
+ return; |
-void RenderWidgetHostViewMac::AckPendingCompositorSwapBuffers() { |
- TRACE_EVENT0("browser", |
- "RenderWidgetHostViewMac::AckPendingCompositorSwapBuffers"); |
- while (!pending_swap_buffers_acks_.empty()) { |
- if (pending_swap_buffers_acks_.front().first != 0) { |
- RenderWidgetHostImpl::AcknowledgeSwapBuffers( |
- pending_swap_buffers_acks_.front().first, |
- pending_swap_buffers_acks_.front().second); |
- } |
- pending_swap_buffers_acks_.erase(pending_swap_buffers_acks_.begin()); |
- } |
+ compositing_iosurface_->SetIOSurface(surface_handle); |
+ // No need to draw the surface if we are inside a drawRect. It will be done |
+ // later. |
+ if (!about_to_validate_and_paint_) |
+ compositing_iosurface_->DrawIOSurface(cocoa_view_); |
+ GotAcceleratedFrame(); |
} |
void RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped( |
@@ -990,8 +971,11 @@ void RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped( |
"RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped"); |
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- if (params.window == compositing_surface_) { |
- CompositorSwapBuffers(params.surface_handle, params.route_id, gpu_host_id); |
+ // Compositor window is always gfx::kNullPluginWindow. |
+ // TODO(jbates) http://crbug.com/105344 This will be removed when there are no |
+ // plugin windows. |
+ if (params.window == gfx::kNullPluginWindow) { |
+ CompositorSwapBuffers(params.surface_handle); |
} else { |
// Deprecated accelerated plugin code path. |
AcceleratedPluginView* view = ViewForPluginWindowHandle(params.window); |
@@ -1005,11 +989,11 @@ void RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped( |
[view setHidden:NO]; |
[view drawView]; |
} |
+ } |
- if (params.route_id != 0) { |
- RenderWidgetHostImpl::AcknowledgeSwapBuffers(params.route_id, |
- gpu_host_id); |
- } |
+ if (params.route_id != 0) { |
+ RenderWidgetHostImpl::AcknowledgeSwapBuffers(params.route_id, |
+ gpu_host_id); |
} |
} |
@@ -1020,8 +1004,11 @@ void RenderWidgetHostViewMac::AcceleratedSurfacePostSubBuffer( |
"RenderWidgetHostViewMac::AcceleratedSurfacePostSubBuffer"); |
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- if (params.window == compositing_surface_) { |
- CompositorSwapBuffers(params.surface_handle, params.route_id, gpu_host_id); |
+ // Compositor window is always gfx::kNullPluginWindow. |
+ // TODO(jbates) http://crbug.com/105344 This will be removed when there are no |
+ // plugin windows. |
+ if (params.window == gfx::kNullPluginWindow) { |
+ CompositorSwapBuffers(params.surface_handle); |
} else { |
// Deprecated accelerated plugin code path. |
AcceleratedPluginView* view = ViewForPluginWindowHandle(params.window); |
@@ -1037,15 +1024,26 @@ void RenderWidgetHostViewMac::AcceleratedSurfacePostSubBuffer( |
[view setHidden:NO]; |
[view drawView]; |
} |
+ } |
- if (params.route_id != 0) { |
- RenderWidgetHostImpl::AcknowledgePostSubBuffer( |
- params.route_id, gpu_host_id); |
- } |
+ if (params.route_id != 0) { |
+ RenderWidgetHostImpl::AcknowledgePostSubBuffer( |
+ params.route_id, gpu_host_id); |
} |
} |
void RenderWidgetHostViewMac::AcceleratedSurfaceSuspend() { |
+ if (compositing_iosurface_.get()) |
+ compositing_iosurface_->UnrefIOSurface(); |
+} |
+ |
+bool RenderWidgetHostViewMac::HasAcceleratedSurface( |
+ const gfx::Size& desired_size) { |
+ return last_frame_was_accelerated_ && |
+ compositing_iosurface_.get() && |
+ compositing_iosurface_->HasIOSurface() && |
+ (desired_size.IsEmpty() || |
+ compositing_iosurface_->io_surface_size() == desired_size); |
} |
void RenderWidgetHostViewMac::OnAcceleratedCompositingStateChange() { |
@@ -1068,8 +1066,10 @@ gfx::Rect RenderWidgetHostViewMac::GetRootWindowBounds() { |
} |
gfx::GLSurfaceHandle RenderWidgetHostViewMac::GetCompositingSurface() { |
- // compositing_surface_ is always gfx::kNullPluginWindow. |
- return gfx::GLSurfaceHandle(compositing_surface_, true); |
+ // Compositor window is always gfx::kNullPluginWindow. |
+ // TODO(jbates) http://crbug.com/105344 This will be removed when there are no |
+ // plugin windows. |
+ return gfx::GLSurfaceHandle(gfx::kNullPluginWindow, true); |
} |
void RenderWidgetHostViewMac::DrawAcceleratedSurfaceInstance( |
@@ -1151,6 +1151,34 @@ void RenderWidgetHostViewMac::ShutdownHost() { |
// Do not touch any members at this point, |this| has been deleted. |
} |
+void RenderWidgetHostViewMac::GotAcceleratedFrame() { |
+ if (!last_frame_was_accelerated_) { |
+ last_frame_was_accelerated_ = true; |
+ |
+ // Need to wipe the software view with transparency to expose the GL |
+ // underlay. Invalidate the whole window to do that. |
+ if (!about_to_validate_and_paint_) { |
+ [cocoa_view_ setNeedsDisplay:YES]; |
+ [cocoa_view_ displayIfNeeded]; |
+ } |
+ |
+ // Delete software backingstore. |
+ BackingStoreManager::RemoveBackingStore(render_widget_host_); |
+ } |
+} |
+ |
+void RenderWidgetHostViewMac::GotSoftwareFrame() { |
+ if (last_frame_was_accelerated_) { |
+ last_frame_was_accelerated_ = false; |
+ |
+ // Forget IOSurface since we are drawing a software frame now. |
+ if (compositing_iosurface_.get() && |
+ compositing_iosurface_->HasIOSurface()) { |
+ compositing_iosurface_->UnrefIOSurface(); |
+ } |
+ } |
+} |
+ |
gfx::Rect RenderWidgetHostViewMac::GetViewCocoaBounds() const { |
return gfx::Rect(NSRectToCGRect([cocoa_view_ bounds])); |
} |
@@ -1360,6 +1388,7 @@ void RenderWidgetHostViewMac::SetTextInputActive(bool active) { |
} |
- (void)mouseEvent:(NSEvent*)theEvent { |
+ TRACE_EVENT0("browser", "RenderWidgetHostViewCocoa::mouseEvent"); |
if (delegate_ && [delegate_ respondsToSelector:@selector(handleEvent:)]) { |
BOOL handled = [delegate_ handleEvent:theEvent]; |
if (handled) |
@@ -1521,6 +1550,7 @@ void RenderWidgetHostViewMac::SetTextInputActive(bool active) { |
} |
- (void)keyEvent:(NSEvent*)theEvent wasKeyEquivalent:(BOOL)equiv { |
+ TRACE_EVENT0("browser", "RenderWidgetHostViewCocoa::keyEvent"); |
DCHECK([theEvent type] != NSKeyDown || |
!equiv == !([theEvent modifierFlags] & NSCommandKeyMask)); |
@@ -1846,6 +1876,7 @@ void RenderWidgetHostViewMac::SetTextInputActive(bool active) { |
} |
- (void)drawRect:(NSRect)dirtyRect { |
+ TRACE_EVENT0("browser", "RenderWidgetHostViewCocoa::drawRect"); |
if (!renderWidgetHostView_->render_widget_host_) { |
// TODO(shess): Consider using something more noticable? |
[[NSColor whiteColor] set]; |
@@ -1853,30 +1884,37 @@ void RenderWidgetHostViewMac::SetTextInputActive(bool active) { |
return; |
} |
- const gfx::Rect damagedRect([self flipNSRectToRect:dirtyRect]); |
- |
- if (renderWidgetHostView_->last_frame_was_accelerated_) { |
- // Draw transparency to expose the GL underlay: |
- // TODO(jbates) avoid doing this every frame. |
- [[NSColor clearColor] set]; |
- NSRectFill(dirtyRect); |
- |
- renderWidgetHostView_->compositing_iosurface_->DrawIOSurface(self); |
- renderWidgetHostView_->AckPendingCompositorSwapBuffers(); |
- return; |
- } |
- |
- // In case the last frame was accelerated, ack any pending swaps to unblock |
- // the GPU process. |
- renderWidgetHostView_->AckPendingCompositorSwapBuffers(); |
- |
DCHECK(!renderWidgetHostView_->about_to_validate_and_paint_); |
+ // GetBackingStore works for both software and accelerated frames. If a |
+ // SwapBuffers occurs while GetBackingStore is blocking, we will continue to |
+ // blit the IOSurface below. |
renderWidgetHostView_->about_to_validate_and_paint_ = true; |
BackingStoreMac* backingStore = static_cast<BackingStoreMac*>( |
renderWidgetHostView_->render_widget_host_->GetBackingStore(true)); |
renderWidgetHostView_->about_to_validate_and_paint_ = false; |
+ const gfx::Rect damagedRect([self flipNSRectToRect:dirtyRect]); |
+ |
+ if (renderWidgetHostView_->last_frame_was_accelerated_ && |
+ renderWidgetHostView_->compositing_iosurface_.get()) { |
+ // Note that this code path is only executed when there's window damage |
+ // (when the window is foregrounded, for example). Normally, GPU frames |
+ // arrive and are drawn during AcceleratedSurfaceBuffersSwapped. |
+ { |
+ TRACE_EVENT0("browser", "NSRectFill"); |
+ // Draw transparency to expose the GL underlay. NSRectFill is extremely |
+ // slow (15ms for a window on a fast MacPro), so this is only done for the |
+ // dirty rect. The composited swap-buffers typically happens outside of |
+ // drawRect to avoid invalidating the entire NSView. |
+ [[NSColor clearColor] set]; |
+ NSRectFill(dirtyRect); |
+ } |
+ |
+ renderWidgetHostView_->compositing_iosurface_->DrawIOSurface(self); |
+ return; |
+ } |
+ |
if (backingStore) { |
gfx::Rect bitmapRect(0, 0, |
backingStore->size().width(), |