return results;
}
+void RemoveLayerFromSuperlayer(
+ base::scoped_nsobject<CompositingIOSurfaceLayer> layer) {
+ // Disable the fade-out animation as the layer is removed.
+ ScopedCAActionDisabler disabler;
+ [layer removeFromSuperlayer];
+}
+
} // namespace
namespace content {
[background_layer_ addSublayer:compositing_iosurface_layer_];
}
-void RenderWidgetHostViewMac::DestroyCompositedIOSurfaceLayer() {
+void RenderWidgetHostViewMac::DestroyCompositedIOSurfaceLayer(
+ DestroyCompositedIOSurfaceLayerBehavior destroy_layer_behavior) {
if (!compositing_iosurface_layer_)
return;
- // Disable the fade-out animation as the layer is removed.
- ScopedCAActionDisabler disabler;
- [compositing_iosurface_layer_ removeFromSuperlayer];
+ if (destroy_layer_behavior == kRemoveLayerFromHierarchy) {
+ // Disable the fade-out animation as the layer is removed.
+ ScopedCAActionDisabler disabler;
+ [compositing_iosurface_layer_ removeFromSuperlayer];
+ }
[compositing_iosurface_layer_ disableCompositing];
compositing_iosurface_layer_.reset();
}
// Any pending frames will not be displayed, so ack them now.
SendPendingSwapAck();
- DestroyCompositedIOSurfaceLayer();
+ DestroyCompositedIOSurfaceLayer(kRemoveLayerFromHierarchy);
compositing_iosurface_.reset();
switch (destroy_context_behavior) {
AddPendingLatencyInfo(latency_info);
+ // If compositing_iosurface_ exists and has been poisoned, destroy it
+ // and allow EnsureCompositedIOSurface to recreate it below. Keep a
+ // reference to the destroyed layer around until after the below call
+ // to LayoutLayers, to avoid flickers.
+ base::ScopedClosureRunner scoped_layer_remover;
+ if (compositing_iosurface_context_ &&
+ compositing_iosurface_context_->HasBeenPoisoned()) {
+ scoped_layer_remover.Reset(
+ base::Bind(RemoveLayerFromSuperlayer, compositing_iosurface_layer_));
+ DestroyCompositedIOSurfaceLayer(kLeaveLayerInHierarchy);
+ DestroyCompositedIOSurfaceAndLayer(kDestroyContext);
+ }
+
// Ensure compositing_iosurface_ and compositing_iosurface_context_ be
// allocated.
if (!EnsureCompositedIOSurface()) {
// Make the context current and update the IOSurface with the handle
// passed in by the swap command.
- gfx::ScopedCGLSetCurrentContext scoped_set_current_context(
- compositing_iosurface_context_->cgl_context());
- if (!compositing_iosurface_->SetIOSurfaceWithContextCurrent(
- compositing_iosurface_context_, surface_handle, size,
- surface_scale_factor)) {
- LOG(ERROR) << "Failed SetIOSurface on CompositingIOSurfaceMac";
- return;
+ {
+ gfx::ScopedCGLSetCurrentContext scoped_set_current_context(
+ compositing_iosurface_context_->cgl_context());
+ if (!compositing_iosurface_->SetIOSurfaceWithContextCurrent(
+ compositing_iosurface_context_, surface_handle, size,
+ surface_scale_factor)) {
+ LOG(ERROR) << "Failed SetIOSurface on CompositingIOSurfaceMac";
+ return;
+ }
}
// Grab video frames now that the IOSurface has been set up. Note that this
&frame, &callback)) {
// Flush the context that updated the IOSurface, to ensure that the
// context that does the copy picks up the correct version.
- glFlush();
+ {
+ gfx::ScopedCGLSetCurrentContext scoped_set_current_context(
+ compositing_iosurface_context_->cgl_context());
+ glFlush();
+ }
compositing_iosurface_->CopyToVideoFrame(
gfx::Rect(size), frame,
base::Bind(callback, present_time));
- DCHECK_EQ(CGLGetCurrentContext(),
- compositing_iosurface_context_->cgl_context());
frame_was_captured = true;
}
}
compositing_iosurface_layer_async_timer_.Reset();
[compositing_iosurface_layer_ gotNewFrame];
} else {
+ gfx::ScopedCGLSetCurrentContext scoped_set_current_context(
+ compositing_iosurface_context_->cgl_context());
DrawIOSurfaceWithoutCoreAnimation();
}
+ // Try to finish previous copy requests after draw to get better pipelining.
+ if (compositing_iosurface_)
+ compositing_iosurface_->CheckIfAllCopiesAreFinished(false);
+
// The IOSurface's size may have changed, so re-layout the layers to take
// this into account. This may force an immediate draw.
LayoutLayers();
void RenderWidgetHostViewMac::SetOverlayView(
RenderWidgetHostViewMac* overlay, const gfx::Point& offset) {
- if (use_core_animation_)
- return;
-
if (overlay_view_)
overlay_view_->underlay_view_.reset();
overlay_view_ = overlay->overlay_view_weak_factory_.GetWeakPtr();
- overlay_view_offset_ = offset;
overlay_view_->underlay_view_ = overlay_view_weak_factory_.GetWeakPtr();
+ if (use_core_animation_)
+ return;
+
+ overlay_view_offset_ = offset;
overlay_view_->underlay_view_has_drawn_ = false;
[cocoa_view_ setNeedsDisplay:YES];
}
void RenderWidgetHostViewMac::RemoveOverlayView() {
- if (use_core_animation_)
- return;
-
if (overlay_view_) {
overlay_view_->underlay_view_.reset();
overlay_view_.reset();
}
+ if (use_core_animation_)
+ return;
+
[cocoa_view_ setNeedsDisplay:YES];
[[cocoa_view_ window] disableScreenUpdatesUntilFlush];
}
GetViewBounds()));
}
- if (compositing_iosurface_) {
+ if (compositing_iosurface_ && !use_core_animation_) {
// This will migrate the context to the appropriate window.
if (!EnsureCompositedIOSurface())
GotAcceleratedCompositingError();
if (!render_widget_host_ || render_widget_host_->is_hidden())
return;
+ // Pausing for the overlay view prevents the underlay from receiving
+ // frames. This may lead to large delays, causing overlaps. If both
+ // overlay and underlay resize at the same time, let them both to have
+ // some time waiting. See crbug.com/352020.
+ if (underlay_view_ &&
+ underlay_view_->render_widget_host_ &&
+ !underlay_view_->render_widget_host_->
+ CanPauseForPendingResizeOrRepaints())
+ return;
+
// Ensure that all frames are acked before waiting for a frame to come in.
// Note that we will draw a frame at the end of this function, so it is safe
// to ack a never-drawn frame here.
respondsToSelector:(@selector(contentsScale))]) {
if (compositing_iosurface_->scale_factor() !=
[compositing_iosurface_layer_ contentsScale]) {
- DestroyCompositedIOSurfaceLayer();
+ DestroyCompositedIOSurfaceLayer(kRemoveLayerFromHierarchy);
EnsureCompositedIOSurfaceLayer();
}
}
- if (compositing_iosurface_ && compositing_iosurface_layer_) {
+ if (compositing_iosurface_ &&
+ compositing_iosurface_->HasIOSurface() &&
+ compositing_iosurface_layer_) {
CGRect layer_bounds = CGRectMake(
0,
0,
// in the layer being anchored to the top-left. Set the layer's frame
// explicitly, since this is more reliable in practice.
if (software_layer_) {
- [software_layer_ setFrame:new_background_frame];
+ bool frame_changed = !CGRectEqualToRect(
+ new_background_frame, [software_layer_ frame]);
+ if (frame_changed) {
+ [software_layer_ setFrame:new_background_frame];
+ [software_layer_ setNeedsDisplay];
+ }
}
}