| Index: ui/accelerated_widget_mac/accelerated_widget_mac.mm
|
| diff --git a/ui/accelerated_widget_mac/accelerated_widget_mac.mm b/ui/accelerated_widget_mac/accelerated_widget_mac.mm
|
| index 2d31cdac759c9f3f7f31335cbcb769aab0e53744..ede33e5ea9d0605c220a82a0efe7637b8444c008 100644
|
| --- a/ui/accelerated_widget_mac/accelerated_widget_mac.mm
|
| +++ b/ui/accelerated_widget_mac/accelerated_widget_mac.mm
|
| @@ -7,15 +7,20 @@
|
| #include <map>
|
|
|
| #include "base/lazy_instance.h"
|
| +#include "base/mac/mac_util.h"
|
| +#include "base/mac/scoped_cftyperef.h"
|
| #include "base/message_loop/message_loop.h"
|
| #include "base/trace_event/trace_event.h"
|
| #include "third_party/skia/include/core/SkCanvas.h"
|
| -#include "ui/accelerated_widget_mac/io_surface_layer.h"
|
| #include "ui/accelerated_widget_mac/surface_handle_types.h"
|
| #include "ui/base/cocoa/animation_utils.h"
|
| #include "ui/gfx/geometry/dip_util.h"
|
| #include "ui/gl/scoped_cgl.h"
|
|
|
| +@interface CALayer (PrivateAPI)
|
| +- (void)setContentsChanged;
|
| +@end
|
| +
|
| namespace ui {
|
| namespace {
|
|
|
| @@ -91,9 +96,8 @@ void AcceleratedWidgetMac::ResetNSView() {
|
| ScopedCAActionDisabler disabler;
|
|
|
| [flipped_layer_ removeFromSuperlayer];
|
| - DestroyIOSurfaceLayer(io_surface_layer_);
|
| DestroyCAContextLayer(ca_context_layer_);
|
| - DestroySoftwareLayer();
|
| + DestroyLocalLayer();
|
|
|
| last_swap_size_dip_ = gfx::Size();
|
| view_ = NULL;
|
| @@ -105,8 +109,6 @@ bool AcceleratedWidgetMac::HasFrameOfSize(
|
| }
|
|
|
| int AcceleratedWidgetMac::GetRendererID() const {
|
| - if (io_surface_layer_)
|
| - return [io_surface_layer_ rendererID];
|
| return 0;
|
| }
|
|
|
| @@ -127,11 +129,9 @@ bool AcceleratedWidgetMac::IsRendererThrottlingDisabled() const {
|
| }
|
|
|
| void AcceleratedWidgetMac::BeginPumpingFrames() {
|
| - [io_surface_layer_ beginPumpingFrames];
|
| }
|
|
|
| void AcceleratedWidgetMac::EndPumpingFrames() {
|
| - [io_surface_layer_ endPumpingFrames];
|
| }
|
|
|
| void AcceleratedWidgetMac::GotAcceleratedFrame(
|
| @@ -156,7 +156,6 @@ void AcceleratedWidgetMac::GotAcceleratedFrame(
|
| // Disable the fade-in or fade-out effect if we create or remove layers.
|
| ScopedCAActionDisabler disabler;
|
|
|
| - last_swap_size_dip_ = gfx::ConvertSizeToDIP(scale_factor, pixel_size);
|
| switch (GetSurfaceHandleType(surface_handle)) {
|
| case kSurfaceHandleTypeIOSurface: {
|
| IOSurfaceID io_surface_id = IOSurfaceIDFromSurfaceHandle(surface_handle);
|
| @@ -169,15 +168,19 @@ void AcceleratedWidgetMac::GotAcceleratedFrame(
|
| break;
|
| }
|
| default:
|
| - LOG(ERROR) << "Unrecognized accelerated frame type.";
|
| + DLOG(ERROR) << "Unrecognized accelerated frame type.";
|
| return;
|
| }
|
| +
|
| + AcknowledgeAcceleratedFrame();
|
| }
|
|
|
| void AcceleratedWidgetMac::GotAcceleratedCAContextFrame(
|
| CAContextID ca_context_id,
|
| const gfx::Size& pixel_size,
|
| float scale_factor) {
|
| + last_swap_size_dip_ = gfx::ConvertSizeToDIP(scale_factor, pixel_size);
|
| +
|
| // In the layer is replaced, keep the old one around until after the new one
|
| // is installed to avoid flashes.
|
| base::scoped_nsobject<CALayerHost> old_ca_context_layer =
|
| @@ -193,119 +196,75 @@ void AcceleratedWidgetMac::GotAcceleratedCAContextFrame(
|
| [flipped_layer_ addSublayer:ca_context_layer_];
|
| }
|
|
|
| - // Acknowledge the frame to unblock the compositor immediately (the GPU
|
| - // process will do any required throttling).
|
| - AcknowledgeAcceleratedFrame();
|
| -
|
| // If this replacing a same-type layer, remove it now that the new layer is
|
| // in the hierarchy.
|
| if (old_ca_context_layer != ca_context_layer_)
|
| DestroyCAContextLayer(old_ca_context_layer);
|
|
|
| // Remove any different-type layers that this is replacing.
|
| - DestroyIOSurfaceLayer(io_surface_layer_);
|
| - DestroySoftwareLayer();
|
| + DestroyLocalLayer();
|
| }
|
|
|
| void AcceleratedWidgetMac::GotAcceleratedIOSurfaceFrame(
|
| IOSurfaceID io_surface_id,
|
| const gfx::Size& pixel_size,
|
| float scale_factor) {
|
| - // In the layer is replaced, keep the old one around until after the new one
|
| - // is installed to avoid flashes.
|
| - base::scoped_nsobject<IOSurfaceLayer> old_io_surface_layer =
|
| - io_surface_layer_;
|
| -
|
| - // Create or re-create an IOSurface layer if needed. If there already exists
|
| - // a layer but it has the wrong scale factor or it was poisoned, re-create the
|
| - // layer.
|
| - bool needs_new_layer =
|
| - !io_surface_layer_ ||
|
| - [io_surface_layer_ hasBeenPoisoned] ||
|
| - [io_surface_layer_ scaleFactor] != scale_factor;
|
| - if (needs_new_layer) {
|
| - io_surface_layer_.reset(
|
| - [[IOSurfaceLayer alloc] initWithClient:this
|
| - withScaleFactor:scale_factor
|
| - needsGLFinishWorkaround:needs_gl_finish_workaround_]);
|
| - if (io_surface_layer_)
|
| - [flipped_layer_ addSublayer:io_surface_layer_];
|
| - else
|
| - LOG(ERROR) << "Failed to create IOSurfaceLayer";
|
| - }
|
| + base::ScopedCFTypeRef<IOSurfaceRef> io_surface(
|
| + IOSurfaceLookup(io_surface_id));
|
| + GotIOSurfaceFrame(io_surface, pixel_size, scale_factor, true);
|
| +}
|
|
|
| - // Open the provided IOSurface.
|
| - if (io_surface_layer_) {
|
| - bool result = [io_surface_layer_ gotFrameWithIOSurface:io_surface_id
|
| - withPixelSize:pixel_size
|
| - withScaleFactor:scale_factor];
|
| - if (!result) {
|
| - DestroyIOSurfaceLayer(io_surface_layer_);
|
| - LOG(ERROR) << "Failed open IOSurface in IOSurfaceLayer";
|
| - }
|
| +void AcceleratedWidgetMac::EnsureLocalLayer() {
|
| + if (!local_layer_) {
|
| + local_layer_.reset([[CALayer alloc] init]);
|
| + // Setting contents gravity is necessary to prevent the layer from being
|
| + // scaled during dyanmic resizes (especially with devtools open).
|
| + [local_layer_ setContentsGravity:kCAGravityTopLeft];
|
| + [flipped_layer_ addSublayer:local_layer_];
|
| }
|
| +}
|
|
|
| - // Give a final complaint if anything with the layer's creation went wrong.
|
| - // This frame will appear blank, the compositor will try to create another,
|
| - // and maybe that will go better.
|
| - if (!io_surface_layer_) {
|
| - LOG(ERROR) << "IOSurfaceLayer is nil, tab will be blank";
|
| - IOSurfaceLayerHitError();
|
| - }
|
| +void AcceleratedWidgetMac::GotIOSurfaceFrame(
|
| + base::ScopedCFTypeRef<IOSurfaceRef> io_surface,
|
| + const gfx::Size& pixel_size,
|
| + float scale_factor,
|
| + bool flip_y) {
|
| + last_swap_size_dip_ = gfx::ConvertSizeToDIP(scale_factor, pixel_size);
|
|
|
| - // Make the CALayer draw and set its size appropriately.
|
| - if (io_surface_layer_) {
|
| - [io_surface_layer_ gotNewFrame];
|
| -
|
| - // Set the bounds of the accelerated layer to match the size of the frame.
|
| - // If the bounds changed, force the content to be displayed immediately.
|
| - CGRect new_layer_bounds = CGRectMake(
|
| - 0, 0, last_swap_size_dip_.width(), last_swap_size_dip_.height());
|
| - bool bounds_changed = !CGRectEqualToRect(
|
| - new_layer_bounds, [io_surface_layer_ bounds]);
|
| - [io_surface_layer_ setBounds:new_layer_bounds];
|
| - if (bounds_changed)
|
| - [io_surface_layer_ setNeedsDisplayAndDisplayAndAck];
|
| - }
|
| + // Disable the fade-in or fade-out effect if we create or remove layers.
|
| + ScopedCAActionDisabler disabler;
|
|
|
| - // If this replacing a same-type layer, remove it now that the new layer is
|
| - // in the hierarchy.
|
| - if (old_io_surface_layer != io_surface_layer_)
|
| - DestroyIOSurfaceLayer(old_io_surface_layer);
|
| + // If there is not a layer for local frames, create one.
|
| + EnsureLocalLayer();
|
|
|
| - // Remove any different-type layers that this is replacing.
|
| - DestroyCAContextLayer(ca_context_layer_);
|
| - DestroySoftwareLayer();
|
| -}
|
| + id new_contents = static_cast<id>(io_surface.get());
|
|
|
| -void AcceleratedWidgetMac::GotSoftwareFrame(float scale_factor,
|
| - SkCanvas* canvas) {
|
| - if (!canvas || !view_)
|
| - return;
|
| + if (new_contents && new_contents == [local_layer_ contents]) {
|
| + [local_layer_ setContentsChanged];
|
| + } else {
|
| + [local_layer_ setContents:new_contents];
|
| + }
|
|
|
| - // Disable the fade-in or fade-out effect if we create or remove layers.
|
| - ScopedCAActionDisabler disabler;
|
| + [local_layer_ setBounds:CGRectMake(0, 0, pixel_size.width() / scale_factor,
|
| + pixel_size.height() / scale_factor)];
|
|
|
| - // If there is not a layer for software frames, create one.
|
| - if (!software_layer_) {
|
| - software_layer_.reset([[SoftwareLayer alloc] init]);
|
| - [flipped_layer_ addSublayer:software_layer_];
|
| + if ([local_layer_ respondsToSelector:(@selector(contentsScale))] &&
|
| + [local_layer_ respondsToSelector:(@selector(setContentsScale:))] &&
|
| + [local_layer_ contentsScale] != scale_factor) {
|
| + DCHECK(base::mac::IsOSLionOrLater());
|
| + [local_layer_ setContentsScale:scale_factor];
|
| }
|
|
|
| - // Set the software layer to draw the provided canvas.
|
| - SkImageInfo info;
|
| - size_t row_bytes;
|
| - const void* pixels = canvas->peekPixels(&info, &row_bytes);
|
| - gfx::Size pixel_size(info.width(), info.height());
|
| - [software_layer_ setContentsToData:pixels
|
| - withRowBytes:row_bytes
|
| - withPixelSize:pixel_size
|
| - withScaleFactor:scale_factor];
|
| - last_swap_size_dip_ = gfx::ConvertSizeToDIP(scale_factor, pixel_size);
|
| + if (flip_y) {
|
| + [local_layer_ setAnchorPoint:CGPointMake(0, 1)];
|
| + [local_layer_ setAffineTransform:CGAffineTransformMakeScale(1.0, -1.0)];
|
| + } else {
|
| + [local_layer_ setAnchorPoint:CGPointMake(0, 0)];
|
| + [local_layer_ setAffineTransform:CGAffineTransformMakeScale(1.0, 1.0)];
|
| + }
|
|
|
| // Remove any different-type layers that this is replacing.
|
| DestroyCAContextLayer(ca_context_layer_);
|
| - DestroyIOSurfaceLayer(io_surface_layer_);
|
| }
|
|
|
| void AcceleratedWidgetMac::DestroyCAContextLayer(
|
| @@ -317,33 +276,11 @@ void AcceleratedWidgetMac::DestroyCAContextLayer(
|
| ca_context_layer_.reset();
|
| }
|
|
|
| -void AcceleratedWidgetMac::DestroyIOSurfaceLayer(
|
| - base::scoped_nsobject<IOSurfaceLayer> io_surface_layer) {
|
| - if (!io_surface_layer)
|
| +void AcceleratedWidgetMac::DestroyLocalLayer() {
|
| + if (!local_layer_)
|
| return;
|
| - [io_surface_layer resetClient];
|
| - [io_surface_layer removeFromSuperlayer];
|
| - if (io_surface_layer == io_surface_layer_)
|
| - io_surface_layer_.reset();
|
| -}
|
| -
|
| -void AcceleratedWidgetMac::DestroySoftwareLayer() {
|
| - if (!software_layer_)
|
| - return;
|
| - [software_layer_ removeFromSuperlayer];
|
| - software_layer_.reset();
|
| -}
|
| -
|
| -bool AcceleratedWidgetMac::IOSurfaceLayerShouldAckImmediately() const {
|
| - // If there is no view then the accelerated layer is not in the view
|
| - // hierarchy and will never draw.
|
| - if (!view_)
|
| - return true;
|
| - return view_->AcceleratedWidgetShouldIgnoreBackpressure();
|
| -}
|
| -
|
| -void AcceleratedWidgetMac::IOSurfaceLayerDidDrawFrame() {
|
| - AcknowledgeAcceleratedFrame();
|
| + [local_layer_ removeFromSuperlayer];
|
| + local_layer_.reset();
|
| }
|
|
|
| void AcceleratedWidgetMac::AcknowledgeAcceleratedFrame() {
|
| @@ -356,18 +293,6 @@ void AcceleratedWidgetMac::AcknowledgeAcceleratedFrame() {
|
| accelerated_latency_info_.clear();
|
| }
|
|
|
| -void AcceleratedWidgetMac::IOSurfaceLayerHitError() {
|
| - // Perform all acks that would have been done if the frame had succeeded, to
|
| - // un-block the compositor and renderer.
|
| - AcknowledgeAcceleratedFrame();
|
| -
|
| - // Poison the context being used and request a mulligan.
|
| - [io_surface_layer_ poisonContextAndSharegroup];
|
| -
|
| - if (view_)
|
| - view_->AcceleratedWidgetHitError();
|
| -}
|
| -
|
| void AcceleratedWidgetMacGotAcceleratedFrame(
|
| gfx::AcceleratedWidget widget, uint64 surface_handle,
|
| const std::vector<ui::LatencyInfo>& latency_info,
|
| @@ -395,12 +320,18 @@ void AcceleratedWidgetMacGotAcceleratedFrame(
|
| }
|
| }
|
|
|
| -void AcceleratedWidgetMacGotSoftwareFrame(
|
| - gfx::AcceleratedWidget widget, float scale_factor, SkCanvas* canvas) {
|
| +void AcceleratedWidgetMacGotIOSurfaceFrame(
|
| + gfx::AcceleratedWidget widget,
|
| + base::ScopedCFTypeRef<IOSurfaceRef> io_surface,
|
| + const gfx::Size& pixel_size,
|
| + float scale_factor,
|
| + bool flip_y) {
|
| AcceleratedWidgetMac* accelerated_widget_mac =
|
| GetHelperFromAcceleratedWidget(widget);
|
| - if (accelerated_widget_mac)
|
| - accelerated_widget_mac->GotSoftwareFrame(scale_factor, canvas);
|
| + if (accelerated_widget_mac) {
|
| + accelerated_widget_mac->GotIOSurfaceFrame(io_surface, pixel_size,
|
| + scale_factor, flip_y);
|
| + }
|
| }
|
|
|
| } // namespace ui
|
|
|