Chromium Code Reviews| 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 200c1aa3355e08033196f1db3924b6b8a37b6592..6d452f6cca7dd1b543f8c024238bdba1c2dee0d6 100644 | 
| --- a/content/browser/renderer_host/render_widget_host_view_mac.mm | 
| +++ b/content/browser/renderer_host/render_widget_host_view_mac.mm | 
| @@ -8,6 +8,7 @@ | 
| #include "base/bind.h" | 
| #include "base/bind_helpers.h" | 
| +#include "base/command_line.h" | 
| #include "base/debug/crash_logging.h" | 
| #include "base/debug/trace_event.h" | 
| #include "base/logging.h" | 
| @@ -25,6 +26,8 @@ | 
| #include "content/browser/accessibility/browser_accessibility_manager_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_context_mac.h" | 
| +#include "content/browser/renderer_host/compositing_iosurface_layer_mac.h" | 
| #include "content/browser/renderer_host/compositing_iosurface_mac.h" | 
| #include "content/browser/renderer_host/render_view_host_impl.h" | 
| #import "content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper.h" | 
| @@ -38,6 +41,7 @@ | 
| #include "content/public/browser/browser_thread.h" | 
| #include "content/public/browser/native_web_keyboard_event.h" | 
| #import "content/public/browser/render_widget_host_view_mac_delegate.h" | 
| +#include "content/public/common/content_switches.h" | 
| #include "skia/ext/platform_canvas.h" | 
| #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h" | 
| #include "third_party/WebKit/Source/WebKit/chromium/public/WebScreenInfo.h" | 
| @@ -53,6 +57,7 @@ | 
| #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h" | 
| #include "ui/gfx/size_conversions.h" | 
| #include "ui/surface/io_surface_support_mac.h" | 
| +#include "ui/base/cocoa/animation_utils.h" | 
| 
 
Avi (use Gerrit)
2013/05/31 23:59:58
alphabetize
 
ccameron
2013/06/01 00:29:45
Done.
 
 | 
| #include "webkit/plugins/npapi/webplugin.h" | 
| using content::BackingStoreMac; | 
| @@ -77,6 +82,10 @@ using WebKit::WebMouseWheelEvent; | 
| - (BOOL)isSpeaking; | 
| @end | 
| +@interface CALayer (LionAPI) | 
| +- (void)setContentsScale:(CGFloat)contentsScale; | 
| +@end | 
| + | 
| // Declare things that are part of the 10.7 SDK. | 
| #if !defined(MAC_OS_X_VERSION_10_7) || \ | 
| MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 | 
| @@ -144,6 +153,10 @@ static float ScaleFactor(NSView* view) { | 
| - (void)keyEvent:(NSEvent*)theEvent wasKeyEquivalent:(BOOL)equiv; | 
| - (void)windowDidChangeBackingProperties:(NSNotification*)notification; | 
| - (void)windowChangedGlobalFrame:(NSNotification*)notification; | 
| +- (void)drawBackingStore:(BackingStoreMac*)backingStore | 
| + dirtyRect:(CGRect)dirtyRect | 
| + inContext:(CGContextRef)context; | 
| +- (void)updateSoftwareLayerScaleFactor; | 
| - (void)checkForPluginImeCancellation; | 
| - (void)updateTabBackingStoreScaleFactor; | 
| - (NSRect)firstViewRectForCharacterRange:(NSRange)theRange | 
| @@ -366,10 +379,14 @@ RenderWidgetHostViewMac::RenderWidgetHostViewMac(RenderWidgetHost* widget) | 
| text_input_type_(ui::TEXT_INPUT_TYPE_NONE), | 
| can_compose_inline_(true), | 
| allow_overlapping_views_(false), | 
| + use_core_animation_(false), | 
| is_loading_(false), | 
| is_hidden_(false), | 
| weak_factory_(this), | 
| fullscreen_parent_host_view_(NULL) { | 
| + use_core_animation_ = CommandLine::ForCurrentProcess()->HasSwitch( | 
| + switches::kUseCoreAnimation); | 
| + | 
| // |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. | 
| @@ -381,6 +398,13 @@ RenderWidgetHostViewMac::RenderWidgetHostViewMac(RenderWidgetHost* widget) | 
| RenderWidgetHostViewMac::~RenderWidgetHostViewMac() { | 
| AckPendingSwapBuffers(); | 
| UnlockMouse(); | 
| + | 
| + // Make sure that the layer doesn't reach into the now-invalid object. | 
| + compositing_iosurface_.reset(); | 
| + if (compositing_iosurface_layer_) | 
| + [compositing_iosurface_layer_ disableCompositing]; | 
| + compositing_iosurface_layer_.reset(); | 
| + | 
| // We are owned by RenderWidgetHostViewCocoa, so if we go away before the | 
| // RenderWidgetHost does we need to tell it not to hold a stale pointer to | 
| // us. | 
| @@ -394,6 +418,7 @@ void RenderWidgetHostViewMac::SetDelegate( | 
| } | 
| void RenderWidgetHostViewMac::SetAllowOverlappingViews(bool overlapping) { | 
| + DCHECK(!overlapping || !use_core_animation_); | 
| allow_overlapping_views_ = overlapping; | 
| } | 
| @@ -512,6 +537,10 @@ int RenderWidgetHostViewMac::window_number() const { | 
| return [window windowNumber]; | 
| } | 
| +float RenderWidgetHostViewMac::scale_factor() const { | 
| + return ScaleFactor(cocoa_view_); | 
| +} | 
| + | 
| RenderWidgetHost* RenderWidgetHostViewMac::GetRenderWidgetHost() const { | 
| return render_widget_host_; | 
| } | 
| @@ -526,7 +555,11 @@ void RenderWidgetHostViewMac::WasShown() { | 
| render_widget_host_->WasShown(); | 
| // We're messing with the window, so do this to ensure no flashes. | 
| - [[cocoa_view_ window] disableScreenUpdatesUntilFlush]; | 
| + if (!use_core_animation_) | 
| + [[cocoa_view_ window] disableScreenUpdatesUntilFlush]; | 
| + | 
| + if (compositing_iosurface_layer_) | 
| + [compositing_iosurface_layer_ setNeedsDisplay]; | 
| } | 
| void RenderWidgetHostViewMac::WasHidden() { | 
| @@ -551,7 +584,8 @@ void RenderWidgetHostViewMac::WasHidden() { | 
| // the NSView and its corresponding OpenGL context. | 
| // disableScreenUpdatesUntilFlush prevents the transparent flash by avoiding | 
| // screen updates until the next tab draws. | 
| - [[cocoa_view_ window] disableScreenUpdatesUntilFlush]; | 
| + if (!use_core_animation_) | 
| + [[cocoa_view_ window] disableScreenUpdatesUntilFlush]; | 
| web_contents_switch_paint_time_ = base::TimeTicks(); | 
| } | 
| @@ -1043,9 +1077,8 @@ void RenderWidgetHostViewMac::PluginImeCompositionCompleted( | 
| } | 
| } | 
| -bool RenderWidgetHostViewMac::CompositorSwapBuffers(uint64 surface_handle, | 
| - const gfx::Size& size, | 
| - float scale_factor) { | 
| +bool RenderWidgetHostViewMac::CompositorSwapBuffers( | 
| + uint64 surface_handle, const gfx::Size& size, float surface_scale_factor) { | 
| if (is_hidden_) | 
| return true; | 
| @@ -1060,7 +1093,7 @@ bool RenderWidgetHostViewMac::CompositorSwapBuffers(uint64 surface_handle, | 
| if (frame_subscriber_->ShouldCaptureFrame(present_time, | 
| &frame, &callback)) { | 
| compositing_iosurface_->SetIOSurface( | 
| - surface_handle, size, scale_factor); | 
| + surface_handle, size, surface_scale_factor); | 
| compositing_iosurface_->CopyToVideoFrame( | 
| gfx::Rect(size), frame, | 
| base::Bind(callback, present_time)); | 
| @@ -1091,18 +1124,43 @@ bool RenderWidgetHostViewMac::CompositorSwapBuffers(uint64 surface_handle, | 
| bool should_post_notification = false; | 
| if (!compositing_iosurface_) { | 
| - CompositingIOSurfaceMac::SurfaceOrder order = allow_overlapping_views_ ? | 
| - CompositingIOSurfaceMac::SURFACE_ORDER_BELOW_WINDOW : | 
| - CompositingIOSurfaceMac::SURFACE_ORDER_ABOVE_WINDOW; | 
| - compositing_iosurface_.reset( | 
| - CompositingIOSurfaceMac::Create(window_number(), order)); | 
| + if (use_core_animation_) { | 
| + if (!compositing_iosurface_layer_) { | 
| + compositing_iosurface_layer_.reset([[CompositingIOSurfaceLayer alloc] | 
| + initWithRenderWidgetHostViewMac:this]); | 
| + } | 
| + if (!compositing_iosurface_layer_) { | 
| + LOG(WARNING) << "Failed to create CALayer for IOSurface"; | 
| + return true; | 
| + } | 
| + if (![compositing_iosurface_layer_ ensureContext]) { | 
| + LOG(WARNING) << "Failed to create context for IOSurface"; | 
| + return true; | 
| + } | 
| + compositing_iosurface_.reset(CompositingIOSurfaceMac::Create( | 
| + [compositing_iosurface_layer_ context])); | 
| + } else { | 
| + CompositingIOSurfaceMac::SurfaceOrder order = allow_overlapping_views_ ? | 
| + CompositingIOSurfaceMac::SURFACE_ORDER_BELOW_WINDOW : | 
| + CompositingIOSurfaceMac::SURFACE_ORDER_ABOVE_WINDOW; | 
| + compositing_iosurface_.reset( | 
| + CompositingIOSurfaceMac::Create(window_number(), order)); | 
| + } | 
| should_post_notification = true; | 
| } | 
| - if (!compositing_iosurface_) | 
| + if (!compositing_iosurface_) { | 
| + LOG(WARNING) << "Failed to create CompositingIOSurfaceMac"; | 
| return true; | 
| + } | 
| - compositing_iosurface_->SetIOSurface(surface_handle, size, scale_factor); | 
| + compositing_iosurface_->SetIOSurface( | 
| + surface_handle, size, surface_scale_factor); | 
| + | 
| + // TODO(ccameron): If we've failed to allocate the GL texture for the | 
| + // IOSurface, or basically anything else along the way, we'll just display | 
| + // a white out, potentially forever. Instead, kick the renderer back to | 
| + // software mode (like a context lost or a GPU process death). | 
| GotAcceleratedFrame(); | 
| @@ -1116,14 +1174,12 @@ bool RenderWidgetHostViewMac::CompositorSwapBuffers(uint64 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_) { | 
| - CompositingIOSurfaceMac::SurfaceOrder order = allow_overlapping_views_ ? | 
| - CompositingIOSurfaceMac::SURFACE_ORDER_BELOW_WINDOW : | 
| - CompositingIOSurfaceMac::SURFACE_ORDER_ABOVE_WINDOW; | 
| - compositing_iosurface_->DrawIOSurface(cocoa_view_, | 
| - ScaleFactor(cocoa_view_), | 
| - window_number(), | 
| - order, | 
| - frame_subscriber_.get()); | 
| + if (use_core_animation_) { | 
| + DCHECK(compositing_iosurface_layer_); | 
| + [compositing_iosurface_layer_ setNeedsDisplay]; | 
| + } else { | 
| + compositing_iosurface_->DrawIOSurface(this); | 
| + } | 
| } | 
| if (should_post_notification && [[cocoa_view_ delegate] | 
| @@ -1131,6 +1187,10 @@ bool RenderWidgetHostViewMac::CompositorSwapBuffers(uint64 surface_handle, | 
| [[cocoa_view_ delegate] compositingIOSurfaceCreated]; | 
| } | 
| + // Don't ack the new frame until it is drawn. | 
| + if (use_core_animation_) | 
| + return false; | 
| + | 
| return true; | 
| } | 
| @@ -1341,6 +1401,9 @@ void RenderWidgetHostViewMac::AcceleratedSurfaceSuspend() { | 
| void RenderWidgetHostViewMac::AcceleratedSurfaceRelease() { | 
| compositing_iosurface_.reset(); | 
| + if (compositing_iosurface_layer_) | 
| + [compositing_iosurface_layer_ disableCompositing]; | 
| + compositing_iosurface_layer_.reset(); | 
| } | 
| bool RenderWidgetHostViewMac::HasAcceleratedSurface( | 
| @@ -1444,12 +1507,19 @@ void RenderWidgetHostViewMac::ShutdownHost() { | 
| } | 
| void RenderWidgetHostViewMac::GotAcceleratedFrame() { | 
| + // Update the scale factor of the layer to match the scale factor of the | 
| + // IOSurface. | 
| + if (compositing_iosurface_layer_) | 
| + [compositing_iosurface_layer_ updateScaleFactor]; | 
| + | 
| 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. | 
| - [cocoa_view_ setNeedsDisplay:YES]; | 
| + if (!use_core_animation_) { | 
| + // Need to wipe the software view with transparency to expose the GL | 
| + // underlay. Invalidate the whole window to do that. | 
| + [cocoa_view_ setNeedsDisplay:YES]; | 
| + } | 
| // Delete software backingstore. | 
| BackingStoreManager::RemoveBackingStore(render_widget_host_); | 
| @@ -1463,9 +1533,17 @@ void RenderWidgetHostViewMac::GotSoftwareFrame() { | 
| AckPendingSwapBuffers(); | 
| // Forget IOSurface since we are drawing a software frame now. | 
| - if (compositing_iosurface_.get() && | 
| - compositing_iosurface_->HasIOSurface()) { | 
| - compositing_iosurface_->ClearDrawable(); | 
| + if (use_core_animation_) { | 
| + compositing_iosurface_.reset(); | 
| + if (compositing_iosurface_layer_) | 
| + [compositing_iosurface_layer_ disableCompositing]; | 
| + compositing_iosurface_layer_.reset(); | 
| + } | 
| + else { | 
| + if (compositing_iosurface_.get() && | 
| 
 
sail
2013/05/31 23:59:14
don't need the .get()
 
ccameron
2013/06/01 00:29:45
Removed all instances of compositing_iosurface_.ge
 
 | 
| + compositing_iosurface_->HasIOSurface()) { | 
| + compositing_iosurface_->ClearDrawable(); | 
| + } | 
| } | 
| } | 
| } | 
| @@ -1585,7 +1663,7 @@ gfx::Rect RenderWidgetHostViewMac::GetScaledOpenGLPixelRect( | 
| src_gl_subrect.set_y(GetViewBounds().height() - rect.bottom()); | 
| return gfx::ToEnclosingRect(gfx::ScaleRect(src_gl_subrect, | 
| - ScaleFactor(cocoa_view_))); | 
| + scale_factor())); | 
| } | 
| } // namespace content | 
| @@ -1610,6 +1688,21 @@ gfx::Rect RenderWidgetHostViewMac::GetScaledOpenGLPixelRect( | 
| focusedPluginIdentifier_ = -1; | 
| deviceScaleFactor_ = ScaleFactor(self); | 
| + if (renderWidgetHostView_->use_core_animation_) { | 
| + CALayer* layer = [CALayer layer]; | 
| + layer.backgroundColor = CGColorGetConstantColor(kCGColorWhite); | 
| + [self setLayer:layer]; | 
| + [self setWantsLayer:YES]; | 
| + | 
| + softwareLayer_.reset([[CALayer alloc] init]); | 
| + [softwareLayer_ setDelegate:self]; | 
| + [softwareLayer_ setAutoresizingMask:kCALayerWidthSizable | | 
| + kCALayerHeightSizable]; | 
| + [softwareLayer_ setContentsGravity:kCAGravityTopLeft]; | 
| + [[self layer] addSublayer:softwareLayer_]; | 
| + [self updateSoftwareLayerScaleFactor]; | 
| + } | 
| + | 
| // OpenGL support: | 
| if ([self respondsToSelector: | 
| @selector(setWantsBestResolutionOpenGLSurface:)]) { | 
| @@ -2131,7 +2224,9 @@ gfx::Rect RenderWidgetHostViewMac::GetScaledOpenGLPixelRect( | 
| // We're messing with the window, so do this to ensure no flashes. This one | 
| // prevents a flash when the current tab is closed. | 
| NSWindow* oldWindow = [self window]; | 
| - [oldWindow disableScreenUpdatesUntilFlush]; | 
| + | 
| + if (!renderWidgetHostView_->use_core_animation_) | 
| + [oldWindow disableScreenUpdatesUntilFlush]; | 
| NSNotificationCenter* notificationCenter = | 
| [NSNotificationCenter defaultCenter]; | 
| @@ -2182,6 +2277,7 @@ gfx::Rect RenderWidgetHostViewMac::GetScaledOpenGLPixelRect( | 
| if (backingStore) // NULL in hardware path. | 
| backingStore->ScaleFactorChanged(scaleFactor); | 
| + [self updateSoftwareLayerScaleFactor]; | 
| renderWidgetHostView_->render_widget_host_->NotifyScreenInfoChanged(); | 
| } | 
| @@ -2238,12 +2334,16 @@ gfx::Rect RenderWidgetHostViewMac::GetScaledOpenGLPixelRect( | 
| [self setNeedsDisplayInRect:renderWidgetHostView_->invalid_rect_]; | 
| renderWidgetHostView_->call_set_needs_display_in_rect_pending_ = false; | 
| renderWidgetHostView_->invalid_rect_ = NSZeroRect; | 
| + | 
| + if (renderWidgetHostView_->compositing_iosurface_layer_) | 
| + [renderWidgetHostView_->compositing_iosurface_layer_ setNeedsDisplay]; | 
| } | 
| // Fills with white the parts of the area to the right and bottom for |rect| | 
| // that intersect |damagedRect|. | 
| - (void)fillBottomRightRemainderOfRect:(gfx::Rect)rect | 
| - dirtyRect:(gfx::Rect)damagedRect { | 
| + dirtyRect:(gfx::Rect)damagedRect | 
| + inContext:(CGContextRef)context { | 
| if (damagedRect.right() > rect.right()) { | 
| int x = std::max(rect.right(), damagedRect.x()); | 
| int y = std::min(rect.bottom(), damagedRect.bottom()); | 
| @@ -2262,8 +2362,9 @@ gfx::Rect RenderWidgetHostViewMac::GetScaledOpenGLPixelRect( | 
| } | 
| NSRect r = [self flipRectToNSRect:gfx::Rect(x, y, width, height)]; | 
| - [[NSColor whiteColor] set]; | 
| - NSRectFill(r); | 
| + CGContextSetFillColorWithColor(context, | 
| + CGColorGetConstantColor(kCGColorWhite)); | 
| + CGContextFillRect(context, NSRectToCGRect(r)); | 
| } | 
| if (damagedRect.bottom() > rect.bottom()) { | 
| int x = damagedRect.x(); | 
| @@ -2283,13 +2384,16 @@ gfx::Rect RenderWidgetHostViewMac::GetScaledOpenGLPixelRect( | 
| } | 
| NSRect r = [self flipRectToNSRect:gfx::Rect(x, y, width, height)]; | 
| - [[NSColor whiteColor] set]; | 
| - NSRectFill(r); | 
| + CGContextSetFillColorWithColor(context, | 
| + CGColorGetConstantColor(kCGColorWhite)); | 
| + CGContextFillRect(context, NSRectToCGRect(r)); | 
| } | 
| } | 
| - (void)drawRect:(NSRect)dirtyRect { | 
| TRACE_EVENT0("browser", "RenderWidgetHostViewCocoa::drawRect"); | 
| + DCHECK(!renderWidgetHostView_->use_core_animation_); | 
| + | 
| if (!renderWidgetHostView_->render_widget_host_) { | 
| // TODO(shess): Consider using something more noticable? | 
| [[NSColor whiteColor] set]; | 
| @@ -2325,19 +2429,22 @@ gfx::Rect RenderWidgetHostViewMac::GetScaledOpenGLPixelRect( | 
| NSRectFill(dirtyRect); | 
| } | 
| - content::CompositingIOSurfaceMac::SurfaceOrder order = | 
| - renderWidgetHostView_->allow_overlapping_views_ | 
| - ? content::CompositingIOSurfaceMac::SURFACE_ORDER_BELOW_WINDOW | 
| - : content::CompositingIOSurfaceMac::SURFACE_ORDER_ABOVE_WINDOW; | 
| renderWidgetHostView_->compositing_iosurface_->DrawIOSurface( | 
| - self, | 
| - ScaleFactor(self), | 
| - renderWidgetHostView_->window_number(), | 
| - order, | 
| - renderWidgetHostView_->frame_subscriber()); | 
| + renderWidgetHostView_.get()); | 
| return; | 
| } | 
| + CGContextRef context = static_cast<CGContextRef>( | 
| + [[NSGraphicsContext currentContext] graphicsPort]); | 
| + [self drawBackingStore:backingStore | 
| + dirtyRect:NSRectToCGRect(dirtyRect) | 
| + inContext:context]; | 
| +} | 
| + | 
| +- (void)drawBackingStore:(BackingStoreMac*)backingStore | 
| + dirtyRect:(CGRect)dirtyRect | 
| + inContext:(CGContextRef)context { | 
| + | 
| 
 
sail
2013/05/31 23:59:14
remove new line?
 
Avi (use Gerrit)
2013/05/31 23:59:58
no blank line
 
ccameron
2013/06/01 00:29:45
Done.
 
 | 
| if (backingStore) { | 
| // Note: All coordinates are in view units, not pixels. | 
| gfx::Rect bitmapRect(0, 0, | 
| @@ -2349,13 +2456,16 @@ gfx::Rect RenderWidgetHostViewMac::GetScaledOpenGLPixelRect( | 
| // smaller and the renderer hasn't yet repainted. | 
| int yOffset = NSHeight([self bounds]) - backingStore->size().height(); | 
| + NSRect nsDirtyRect = NSMakeRect(dirtyRect.origin.x, | 
| + dirtyRect.origin.y, | 
| + dirtyRect.size.width, | 
| + dirtyRect.size.height); | 
| + const gfx::Rect damagedRect([self flipNSRectToRect:nsDirtyRect]); | 
| + | 
| gfx::Rect paintRect = gfx::IntersectRects(bitmapRect, damagedRect); | 
| if (!paintRect.IsEmpty()) { | 
| // if we have a CGLayer, draw that into the window | 
| if (backingStore->cg_layer()) { | 
| - CGContextRef context = static_cast<CGContextRef>( | 
| - [[NSGraphicsContext currentContext] graphicsPort]); | 
| - | 
| // TODO: add clipping to dirtyRect if it improves drawing performance. | 
| CGContextDrawLayerAtPoint(context, CGPointMake(0.0, yOffset), | 
| backingStore->cg_layer()); | 
| @@ -2363,8 +2473,6 @@ gfx::Rect RenderWidgetHostViewMac::GetScaledOpenGLPixelRect( | 
| // if we haven't created a layer yet, draw the cached bitmap into | 
| // the window. The CGLayer will be created the next time the renderer | 
| // paints. | 
| - CGContextRef context = static_cast<CGContextRef>( | 
| - [[NSGraphicsContext currentContext] graphicsPort]); | 
| base::mac::ScopedCFTypeRef<CGImageRef> image( | 
| CGBitmapContextCreateImage(backingStore->cg_bitmap())); | 
| CGRect imageRect = bitmapRect.ToCGRect(); | 
| @@ -2374,7 +2482,9 @@ gfx::Rect RenderWidgetHostViewMac::GetScaledOpenGLPixelRect( | 
| } | 
| // Fill the remaining portion of the damagedRect with white | 
| - [self fillBottomRightRemainderOfRect:bitmapRect dirtyRect:damagedRect]; | 
| + [self fillBottomRightRemainderOfRect:bitmapRect | 
| + dirtyRect:damagedRect | 
| + inContext:context]; | 
| if (!renderWidgetHostView_->whiteout_start_time_.is_null()) { | 
| base::TimeDelta whiteout_duration = base::TimeTicks::Now() - | 
| @@ -2397,8 +2507,9 @@ gfx::Rect RenderWidgetHostViewMac::GetScaledOpenGLPixelRect( | 
| base::TimeTicks(); | 
| } | 
| } else { | 
| - [[NSColor whiteColor] set]; | 
| - NSRectFill(dirtyRect); | 
| + CGContextSetFillColorWithColor(context, | 
| + CGColorGetConstantColor(kCGColorWhite)); | 
| + CGContextFillRect(context, dirtyRect); | 
| if (renderWidgetHostView_->whiteout_start_time_.is_null()) | 
| renderWidgetHostView_->whiteout_start_time_ = base::TimeTicks::Now(); | 
| } | 
| @@ -3371,6 +3482,50 @@ extern NSString *NSTextInputReplacementRangeAttributeName; | 
| renderWidgetHostView_->KillSelf(); | 
| } | 
| +- (void)updateSoftwareLayerScaleFactor { | 
| + if (![softwareLayer_ respondsToSelector:@selector(setContentsScale:)]) | 
| + return; | 
| + | 
| + ScopedCAActionDisabler disabler; | 
| + [softwareLayer_ setContentsScale:deviceScaleFactor_]; | 
| +} | 
| + | 
| +// Delegate methods for the software CALayer | 
| +- (void)drawLayer:(CALayer*)layer | 
| + inContext:(CGContextRef)context { | 
| + DCHECK(renderWidgetHostView_->use_core_animation_); | 
| + DCHECK([layer isEqual:softwareLayer_]); | 
| + | 
| + CGRect clipRect = CGContextGetClipBoundingBox(context); | 
| + | 
| + if (!renderWidgetHostView_->render_widget_host_ || | 
| + renderWidgetHostView_->is_hidden()) { | 
| + CGContextSetFillColorWithColor(context, | 
| + CGColorGetConstantColor(kCGColorWhite)); | 
| + CGContextFillRect(context, clipRect); | 
| + return; | 
| + } | 
| + | 
| + 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; | 
| + | 
| + [self drawBackingStore:backingStore | 
| + dirtyRect:clipRect | 
| + inContext:context]; | 
| +} | 
| + | 
| +- (void)setNeedsDisplay:(BOOL)flag { | 
| + [softwareLayer_ setNeedsDisplay]; | 
| + [super setNeedsDisplay:flag]; | 
| +} | 
| + | 
| +- (void)setNeedsDisplayInRect:(NSRect)rect { | 
| + [softwareLayer_ setNeedsDisplayInRect:NSRectToCGRect(rect)]; | 
| + [super setNeedsDisplayInRect:rect]; | 
| +} | 
| + | 
| @end | 
| // | 
| @@ -3401,4 +3556,10 @@ extern NSString *NSTextInputReplacementRangeAttributeName; | 
| return YES; | 
| } | 
| +- (BOOL)isOpaque { | 
| + if (renderWidgetHostView_->use_core_animation_) | 
| + return YES; | 
| + return [super isOpaque]; | 
| +} | 
| + | 
| @end |