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

Unified 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 side-by-side diff with in-line comments
Download patch
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 04051758b6540a2c48e5c62ad6282fb8ce251968..d8ee48152ed56a186637bcfd8ec921b32322cbec 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -420,6 +420,8 @@ RenderWidgetHostViewMac::RenderWidgetHostViewMac(RenderWidgetHost* widget)
last_frame_was_accelerated_(false),
text_input_type_(ui::TEXT_INPUT_TYPE_NONE),
can_compose_inline_(true),
+ software_framebuffer_(new SoftwareFramebuffer(
+ this, RenderWidgetHostImpl::From(widget))),
allow_overlapping_views_(false),
use_core_animation_(false),
is_loading_(false),
@@ -734,6 +736,7 @@ void RenderWidgetHostViewMac::WasShown() {
web_contents_switch_paint_time_ = base::TimeTicks::Now();
is_hidden_ = false;
render_widget_host_->WasShown();
+ software_framebuffer_->WasShown();
// We're messing with the window, so do this to ensure no flashes.
if (!use_core_animation_)
@@ -758,6 +761,7 @@ void RenderWidgetHostViewMac::WasHidden() {
// If we have a renderer, then inform it that we are being hidden so it can
// reduce its resource utilization.
render_widget_host_->WasHidden();
+ software_framebuffer_->WasHidden();
// There can be a transparent flash as this view is removed and the next is
// added, because of OSX windowing races between displaying the contents of
@@ -1221,6 +1225,24 @@ void RenderWidgetHostViewMac::EndFrameSubscription() {
frame_subscriber_.reset();
}
+void RenderWidgetHostViewMac::OnSwapCompositorFrame(
+ uint32 output_surface_id, scoped_ptr<cc::CompositorFrame> frame) {
+ // Only software compositor frames are accepted.
+ if (!frame->software_frame_data) {
+ render_widget_host_->GetProcess()->ReceivedBadMessage();
+ return;
+ }
+
+ GotSoftwareFrame();
+
+ software_framebuffer_->SwapToNewFrame(
+ output_surface_id,
+ frame->software_frame_data.get(),
+ frame->metadata.device_scale_factor);
+
+ [cocoa_view_ setNeedsDisplay:YES];
+}
+
// Sets whether or not to accept first responder status.
void RenderWidgetHostViewMac::SetTakesFocusOnlyOnMouseDown(bool flag) {
[cocoa_view_ setTakesFocusOnlyOnMouseDown:flag];
@@ -1657,11 +1679,18 @@ void RenderWidgetHostViewMac::AcceleratedSurfaceRelease() {
bool RenderWidgetHostViewMac::HasAcceleratedSurface(
const gfx::Size& desired_size) {
- return last_frame_was_accelerated_ &&
- compositing_iosurface_ &&
- compositing_iosurface_->HasIOSurface() &&
- (desired_size.IsEmpty() ||
- compositing_iosurface_->dip_io_surface_size() == desired_size);
+ if (last_frame_was_accelerated_) {
+ return (compositing_iosurface_ &&
+ compositing_iosurface_->HasIOSurface() &&
+ (desired_size.IsEmpty() ||
+ compositing_iosurface_->dip_io_surface_size() == desired_size));
+ } else {
+ return (software_framebuffer_->HasCurrentFrame() &&
+ (desired_size.IsEmpty() ||
+ software_framebuffer_->GetCurrentFrameSizeInDIP() ==
+ desired_size));
+ }
+ return false;
}
void RenderWidgetHostViewMac::AboutToWaitForBackingStoreMsg() {
@@ -1771,6 +1800,9 @@ void RenderWidgetHostViewMac::GotAcceleratedFrame() {
// Delete software backingstore.
BackingStoreManager::RemoveBackingStore(render_widget_host_);
+
+ // Delete the software compositing frame if one exists.
+ software_framebuffer_->DiscardCurrentFrame();
}
}
@@ -2724,29 +2756,63 @@ void RenderWidgetHostViewMac::FrameSwapped() {
- (void)drawBackingStore:(BackingStoreMac*)backingStore
dirtyRect:(CGRect)dirtyRect
inContext:(CGContextRef)context {
- if (backingStore) {
+ content::SoftwareFramebuffer* software_framebuffer =
+ renderWidgetHostView_->software_framebuffer_->HasCurrentFrame() ?
+ renderWidgetHostView_->software_framebuffer_.get() : NULL;
+ DCHECK(!backingStore || !software_framebuffer);
+
+ if (backingStore || software_framebuffer) {
// Note: All coordinates are in view units, not pixels.
- gfx::Rect bitmapRect(0, 0,
- backingStore->size().width(),
- backingStore->size().height());
+ gfx::Rect bitmapRect(software_framebuffer ?
+ software_framebuffer->GetCurrentFrameSizeInDIP() :
+ backingStore->size());
// Specify the proper y offset to ensure that the view is rooted to the
// upper left corner. This can be negative, if the window was resized
// smaller and the renderer hasn't yet repainted.
- int yOffset = NSHeight([self bounds]) - backingStore->size().height();
+ int yOffset = NSHeight([self bounds]) - bitmapRect.height();
NSRect nsDirtyRect = NSRectFromCGRect(dirtyRect);
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()) {
+ if (software_framebuffer) {
+ // If a software compositor framebuffer is present, draw using that.
+ gfx::Size sizeInPixels =
+ software_framebuffer->GetCurrentFrameSizeInPixels();
+
+ base::ScopedCFTypeRef<CGDataProviderRef> dataProvider(
+ CGDataProviderCreateWithData(
+ NULL,
+ software_framebuffer->GetCurrentFramePixels(),
+ 4 * sizeInPixels.width() * sizeInPixels.height(),
+ NULL));
+
+ base::ScopedCFTypeRef<CGImageRef> image(
+ CGImageCreate(
+ sizeInPixels.width(),
+ sizeInPixels.height(),
+ 8,
+ 32,
+ 4 * sizeInPixels.width(),
+ base::mac::GetSystemColorSpace(),
+ kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host,
+ dataProvider,
+ NULL,
+ false,
+ kCGRenderingIntentDefault));
+
+ CGRect imageRect = bitmapRect.ToCGRect();
+ imageRect.origin.y = yOffset;
+ CGContextDrawImage(context, imageRect, image);
+ } else if (backingStore->cg_layer()) {
+ // If we have a CGLayer, draw that into the window
// TODO: add clipping to dirtyRect if it improves drawing performance.
CGContextDrawLayerAtPoint(context, CGPointMake(0.0, yOffset),
backingStore->cg_layer());
} else {
- // if we haven't created a layer yet, draw the cached bitmap into
+ // 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.
base::ScopedCFTypeRef<CGImageRef> image(

Powered by Google App Engine
This is Rietveld 408576698