diff --git a/components/exo/shell_surface.cc b/components/exo/shell_surface.cc index 3c8b030c..4f9ebb4 100644 --- a/components/exo/shell_surface.cc +++ b/components/exo/shell_surface.cc
@@ -378,11 +378,15 @@ if (widget_) { UpdateWidgetBounds(); - // Only allow the shelf to recognize this window if the input bounds + gfx::Point surface_origin = GetSurfaceOrigin(); + gfx::Rect hit_test_bounds = + surface_->GetHitTestBounds() + surface_origin.OffsetFromOrigin(); + + // Only allow the shelf to recognize this window if the hit-test bounds // contains the widget bounds. This prevents shaped windows that might // only occupy a small area of the widget from dimming the shelf when // maximized. - bool ignored_by_shelf = !surface_->GetInputBounds().Contains( + bool ignored_by_shelf = !hit_test_bounds.Contains( gfx::Rect(widget_->GetNativeWindow()->bounds().size())); // Update state and shelf visibility if |ignored_by_shelf| changed. @@ -394,8 +398,7 @@ } // Update surface bounds. - surface_->SetBounds( - gfx::Rect(GetSurfaceOrigin(), surface_->layer()->size())); + surface_->SetBounds(gfx::Rect(surface_origin, surface_->layer()->size())); // Show widget if not already visible. if (!widget_->IsClosed() && !widget_->IsVisible())
diff --git a/components/exo/surface.cc b/components/exo/surface.cc index 9b63799..880d4de 100644 --- a/components/exo/surface.cc +++ b/components/exo/surface.cc
@@ -416,14 +416,17 @@ } } -gfx::Rect Surface::GetInputBounds() const { - return gfx::SkIRectToRect(input_region_.getBounds()); -} - bool Surface::IsSynchronized() const { return delegate_ ? delegate_->IsSurfaceSynchronized() : false; } +gfx::Rect Surface::GetHitTestBounds() const { + SkIRect bounds = input_region_.getBounds(); + if (!bounds.intersect(gfx::RectToSkIRect(gfx::Rect(layer()->size())))) + return gfx::Rect(); + return gfx::SkIRectToRect(bounds); +} + bool Surface::HitTestRect(const gfx::Rect& rect) const { if (HasHitTestMask()) return input_region_.intersects(gfx::RectToSkIRect(rect));
diff --git a/components/exo/surface.h b/components/exo/surface.h index b4cbf92..a7be89e 100644 --- a/components/exo/surface.h +++ b/components/exo/surface.h
@@ -101,8 +101,8 @@ // Returns true if surface is in synchronized mode. bool IsSynchronized() const; - // Returns the input bounds of the surface. - gfx::Rect GetInputBounds() const; + // Returns the bounds of the current input region of surface. + gfx::Rect GetHitTestBounds() const; // Returns true if |rect| intersects this surface's bounds. bool HitTestRect(const gfx::Rect& rect) const;
diff --git a/gpu/ipc/service/image_transport_surface_overlay_mac.h b/gpu/ipc/service/image_transport_surface_overlay_mac.h index dde6109..e455cf00 100644 --- a/gpu/ipc/service/image_transport_surface_overlay_mac.h +++ b/gpu/ipc/service/image_transport_surface_overlay_mac.h
@@ -45,7 +45,6 @@ gfx::Size GetSize() override; void* GetHandle() override; bool OnMakeCurrent(gfx::GLContext* context) override; - bool SetBackbufferAllocation(bool allocated) override; bool ScheduleOverlayPlane(int z_order, gfx::OverlayTransform transform, gl::GLImage* image, @@ -67,9 +66,6 @@ void OnGpuSwitched() override; private: - class PendingSwap; - class OverlayPlane; - ~ImageTransportSurfaceOverlayMac() override; void SetLatencyInfo(const std::vector<ui::LatencyInfo>& latency_info); @@ -85,31 +81,6 @@ std::vector<ui::LatencyInfo> latency_info); gfx::SwapResult SwapBuffersInternal(const gfx::Rect& pixel_damage_rect); - // Returns true if the front of |pending_swaps_| has completed, or has timed - // out by |now|. - bool IsFirstPendingSwapReadyToDisplay( - const base::TimeTicks& now); - // Sets the CALayer contents to the IOSurface for the front of - // |pending_swaps_|, and removes it from the queue. - void DisplayFirstPendingSwapImmediately(); - // Force that all of |pending_swaps_| displayed immediately, and the list be - // cleared. - void DisplayAndClearAllPendingSwaps(); - // Callback issued during the next vsync period ofter a SwapBuffers call, - // to check if the swap is completed, and display the frame. Note that if - // another SwapBuffers happens before this callback, the pending swap will - // be tested at that time, too. - void CheckPendingSwapsCallback(); - // Function to post the above callback. The argument |now| is passed as an - // argument to avoid redundant calls to base::TimeTicks::Now. - void PostCheckPendingSwapsCallbackIfNeeded(const base::TimeTicks& now); - - // Return the time of |interval_fraction| of the way through the next - // vsync period that starts after |from|. If the vsync parameters are not - // valid then return |from|. - base::TimeTicks GetNextVSyncTimeAfter( - const base::TimeTicks& from, double interval_fraction); - GpuChannelManager* manager_; base::WeakPtr<GpuCommandBufferStub> stub_; SurfaceHandle handle_; @@ -131,26 +102,14 @@ scoped_ptr<CALayerPartialDamageTree> pending_partial_damage_tree_; scoped_ptr<CALayerTree> pending_ca_layer_tree_; - // A queue of all frames that have been created by SwapBuffersInternal but - // have not yet been displayed. This queue is checked at the beginning of - // every swap and also by a callback. - std::deque<linked_ptr<PendingSwap>> pending_swaps_; - // The planes that are currently being displayed on the screen. scoped_ptr<CALayerPartialDamageTree> current_partial_damage_tree_; scoped_ptr<CALayerTree> current_ca_layer_tree_; - // The time of the last swap was issued. If this is more than two vsyncs, then - // use the simpler non-smooth animation path. - base::TimeTicks last_swap_time_; - // The vsync information provided by the browser. bool vsync_parameters_valid_; base::TimeTicks vsync_timebase_; base::TimeDelta vsync_interval_; - - base::Timer display_pending_swap_timer_; - base::WeakPtrFactory<ImageTransportSurfaceOverlayMac> weak_factory_; }; } // namespace gpu
diff --git a/gpu/ipc/service/image_transport_surface_overlay_mac.mm b/gpu/ipc/service/image_transport_surface_overlay_mac.mm index 4eea4a1..876b23ed 100644 --- a/gpu/ipc/service/image_transport_surface_overlay_mac.mm +++ b/gpu/ipc/service/image_transport_surface_overlay_mac.mm
@@ -42,25 +42,6 @@ namespace { -// Don't let a frame draw until 5% of the way through the next vsync interval -// after the call to SwapBuffers. This slight offset is to ensure that skew -// doesn't result in the frame being presented to the previous vsync interval. -const double kVSyncIntervalFractionForEarliestDisplay = 0.05; - -// After doing a glFlush and putting in a fence in SwapBuffers, post a task to -// query the fence 50% of the way through the next vsync interval. If we are -// trying to animate smoothly, then want to query the fence at the next -// SwapBuffers. For this reason we schedule the callback for a long way into -// the next frame. -const double kVSyncIntervalFractionForDisplayCallback = 0.5; - -// If swaps arrive regularly and nearly at the vsync rate, then attempt to -// make animation smooth (each frame is shown for one vsync interval) by sending -// them to the window server only when their GL work completes. If frames are -// not coming in with each vsync, then just throw them at the window server as -// they come. -const double kMaximumVSyncsBetweenSwapsForSmoothAnimation = 1.5; - void CheckGLErrors(const char* msg) { GLenum gl_error; while ((gl_error = glGetError()) != GL_NO_ERROR) { @@ -73,10 +54,6 @@ } // namespace -@interface CALayer(Private) --(void)setContentsChanged; -@end - namespace gpu { scoped_refptr<gfx::GLSurface> ImageTransportSurfaceCreateNativeSurface( @@ -86,33 +63,6 @@ return new ImageTransportSurfaceOverlayMac(manager, stub, handle); } -class ImageTransportSurfaceOverlayMac::PendingSwap { - public: - PendingSwap() {} - ~PendingSwap() { DCHECK(!gl_fence); } - - gfx::Size pixel_size; - float scale_factor; - gfx::Rect pixel_damage_rect; - - scoped_ptr<CALayerPartialDamageTree> partial_damage_tree; - scoped_ptr<CALayerTree> ca_layer_tree; - std::vector<ui::LatencyInfo> latency_info; - - // A fence object, and the CGL context it was issued in. - base::ScopedTypeRef<CGLContextObj> cgl_context; - scoped_ptr<gfx::GLFence> gl_fence; - - // The earliest time that this frame may be drawn. A frame is not allowed - // to draw until a fraction of the way through the vsync interval after its - // This extra latency is to allow wiggle-room for smoothness. - base::TimeTicks earliest_display_time_allowed; - - // The time that this will wake up and draw, if a following swap does not - // cause it to draw earlier. - base::TimeTicks target_display_time; -}; - ImageTransportSurfaceOverlayMac::ImageTransportSurfaceOverlayMac( GpuChannelManager* manager, GpuCommandBufferStub* stub, @@ -123,9 +73,7 @@ use_remote_layer_api_(ui::RemoteLayerAPISupported()), scale_factor_(1), gl_renderer_id_(0), - vsync_parameters_valid_(false), - display_pending_swap_timer_(true, false), - weak_factory_(this) { + vsync_parameters_valid_(false) { manager_->AddBufferPresentedCallback( handle_, base::Bind(&ImageTransportSurfaceOverlayMac::BufferPresented, base::Unretained(this))); @@ -166,8 +114,6 @@ } void ImageTransportSurfaceOverlayMac::Destroy() { - DisplayAndClearAllPendingSwaps(); - current_partial_damage_tree_.reset(); current_ca_layer_tree_.reset(); } @@ -220,130 +166,33 @@ const gfx::Rect& pixel_damage_rect) { TRACE_EVENT0("gpu", "ImageTransportSurfaceOverlayMac::SwapBuffersInternal"); - // Use the same concept of 'now' for the entire function. The duration of - // this function only affect the result if this function lasts across a vsync - // boundary, in which case smooth animation is out the window anyway. - const base::TimeTicks now = base::TimeTicks::Now(); - - // Decide if the frame should be drawn immediately, or if we should wait until - // its work finishes before drawing immediately. - bool display_immediately = false; - if (vsync_parameters_valid_ && - now - last_swap_time_ > - kMaximumVSyncsBetweenSwapsForSmoothAnimation * vsync_interval_) { - display_immediately = true; - } - last_swap_time_ = now; - - // If the previous swap is ready to display, do it before flushing the - // new swap. It is desirable to always be hitting this path when trying to - // animate smoothly with vsync. - if (!pending_swaps_.empty()) { - if (IsFirstPendingSwapReadyToDisplay(now)) - DisplayFirstPendingSwapImmediately(); - } - - // The remainder of the function will populate the PendingSwap structure and - // then enqueue it. - linked_ptr<PendingSwap> new_swap(new PendingSwap); - new_swap->pixel_size = pixel_size_; - new_swap->scale_factor = scale_factor_; - new_swap->pixel_damage_rect = pixel_damage_rect; - new_swap->partial_damage_tree.swap(pending_partial_damage_tree_); - new_swap->ca_layer_tree.swap(pending_ca_layer_tree_); - new_swap->latency_info.swap(latency_info_); - - // A flush is required to ensure that all content appears in the layer. + // A glFlush is necessary to ensure correct content appears. A glFinish + // appears empirically to be the best way to get maximum performance when + // GPU bound. { gfx::ScopedSetGLToRealGLApi scoped_set_gl_api; - TRACE_EVENT0("gpu", "ImageTransportSurfaceOverlayMac::glFlush"); - CheckGLErrors("before flushing frame"); - new_swap->cgl_context.reset(CGLGetCurrentContext(), - base::scoped_policy::RETAIN); - if (gfx::GLFence::IsSupported() && !display_immediately) - new_swap->gl_fence.reset(gfx::GLFence::Create()); - else - glFlush(); - CheckGLErrors("while flushing frame"); + TRACE_EVENT0("gpu", "ImageTransportSurfaceOverlayMac::glFinish"); + CheckGLErrors("Before finish"); + glFinish(); + CheckGLErrors("After finish"); } - // Compute the deadlines for drawing this frame. - if (display_immediately) { - new_swap->earliest_display_time_allowed = now; - new_swap->target_display_time = now; - } else { - new_swap->earliest_display_time_allowed = - GetNextVSyncTimeAfter(now, kVSyncIntervalFractionForEarliestDisplay); - new_swap->target_display_time = - GetNextVSyncTimeAfter(now, kVSyncIntervalFractionForDisplayCallback); - } - - pending_swaps_.push_back(new_swap); - if (display_immediately) - DisplayFirstPendingSwapImmediately(); - else - PostCheckPendingSwapsCallbackIfNeeded(now); - return gfx::SwapResult::SWAP_ACK; -} - -bool ImageTransportSurfaceOverlayMac::IsFirstPendingSwapReadyToDisplay( - const base::TimeTicks& now) { - DCHECK(!pending_swaps_.empty()); - linked_ptr<PendingSwap> swap = pending_swaps_.front(); - - // Frames are disallowed from drawing until the vsync interval after their - // swap is issued. - if (now < swap->earliest_display_time_allowed) - return false; - - // If we've passed that marker, then wait for the work behind the fence to - // complete. - if (swap->gl_fence) { - gfx::ScopedSetGLToRealGLApi scoped_set_gl_api; - gfx::ScopedCGLSetCurrentContext scoped_set_current(swap->cgl_context); - - CheckGLErrors("before waiting on fence"); - if (!swap->gl_fence->HasCompleted()) { - TRACE_EVENT0("gpu", "ImageTransportSurfaceOverlayMac::ClientWait"); - swap->gl_fence->ClientWait(); - } - swap->gl_fence.reset(); - CheckGLErrors("after waiting on fence"); - } - return true; -} - -void ImageTransportSurfaceOverlayMac::DisplayFirstPendingSwapImmediately() { - TRACE_EVENT0("gpu", - "ImageTransportSurfaceOverlayMac::DisplayFirstPendingSwapImmediately"); - DCHECK(!pending_swaps_.empty()); - linked_ptr<PendingSwap> swap = pending_swaps_.front(); - - // If there is a fence for this object, delete it. - if (swap->gl_fence) { - gfx::ScopedSetGLToRealGLApi scoped_set_gl_api; - gfx::ScopedCGLSetCurrentContext scoped_set_current(swap->cgl_context); - - CheckGLErrors("before deleting active fence"); - swap->gl_fence.reset(); - CheckGLErrors("while deleting active fence"); - } + base::TimeTicks finish_time = base::TimeTicks::Now(); // Update the CALayer hierarchy. { - gfx::RectF pixel_damage_rect = gfx::RectF(swap->pixel_damage_rect); ScopedCAActionDisabler disabler; - if (swap->ca_layer_tree) { - swap->ca_layer_tree->CommitScheduledCALayers( + if (pending_ca_layer_tree_) { + pending_ca_layer_tree_->CommitScheduledCALayers( ca_root_layer_.get(), std::move(current_ca_layer_tree_), - swap->scale_factor); - current_ca_layer_tree_.swap(swap->ca_layer_tree); + scale_factor_); + current_ca_layer_tree_.swap(pending_ca_layer_tree_); current_partial_damage_tree_.reset(); - } else if (swap->partial_damage_tree) { - swap->partial_damage_tree->CommitCALayers( + } else if (pending_partial_damage_tree_) { + pending_partial_damage_tree_->CommitCALayers( ca_root_layer_.get(), std::move(current_partial_damage_tree_), - swap->scale_factor, swap->pixel_damage_rect); - current_partial_damage_tree_.swap(swap->partial_damage_tree); + scale_factor_, pixel_damage_rect); + current_partial_damage_tree_.swap(pending_partial_damage_tree_); current_ca_layer_tree_.reset(); } else { TRACE_EVENT0("gpu", "Blank frame: No overlays or CALayers"); @@ -351,18 +200,15 @@ current_partial_damage_tree_.reset(); current_ca_layer_tree_.reset(); } - swap->ca_layer_tree.reset(); - swap->partial_damage_tree.reset(); } // Update the latency info to reflect the swap time. - base::TimeTicks swap_time = base::TimeTicks::Now(); - for (auto latency_info : swap->latency_info) { + for (auto latency_info : latency_info_) { latency_info.AddLatencyNumberWithTimestamp( - ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, 0, 0, swap_time, 1); + ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, 0, 0, finish_time, 1); latency_info.AddLatencyNumberWithTimestamp( ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0, - swap_time, 1); + finish_time, 1); } // Send acknowledgement to the browser. @@ -374,51 +220,15 @@ io_surface.reset(IOSurfaceCreateMachPort( current_partial_damage_tree_->RootLayerIOSurface())); } - gfx::Size size = swap->pixel_size; - float scale_factor = swap->scale_factor; - std::vector<ui::LatencyInfo> latency_info; - latency_info.swap(swap->latency_info); - SendAcceleratedSurfaceBuffersSwapped(handle_, ca_context_id, io_surface, size, - scale_factor, std::move(latency_info)); + SendAcceleratedSurfaceBuffersSwapped(handle_, ca_context_id, io_surface, + pixel_size_, scale_factor_, + std::move(latency_info_)); - // Remove this from the queue, and reset any callback timers. - pending_swaps_.pop_front(); -} - -void ImageTransportSurfaceOverlayMac::DisplayAndClearAllPendingSwaps() { - TRACE_EVENT0("gpu", - "ImageTransportSurfaceOverlayMac::DisplayAndClearAllPendingSwaps"); - while (!pending_swaps_.empty()) - DisplayFirstPendingSwapImmediately(); -} - -void ImageTransportSurfaceOverlayMac::CheckPendingSwapsCallback() { - TRACE_EVENT0("gpu", - "ImageTransportSurfaceOverlayMac::CheckPendingSwapsCallback"); - - if (pending_swaps_.empty()) - return; - - const base::TimeTicks now = base::TimeTicks::Now(); - if (IsFirstPendingSwapReadyToDisplay(now)) - DisplayFirstPendingSwapImmediately(); - PostCheckPendingSwapsCallbackIfNeeded(now); -} - -void ImageTransportSurfaceOverlayMac::PostCheckPendingSwapsCallbackIfNeeded( - const base::TimeTicks& now) { - TRACE_EVENT0("gpu", - "ImageTransportSurfaceOverlayMac::PostCheckPendingSwapsCallbackIfNeeded"); - - if (pending_swaps_.empty()) { - display_pending_swap_timer_.Stop(); - } else { - display_pending_swap_timer_.Start( - FROM_HERE, - pending_swaps_.front()->target_display_time - now, - base::Bind(&ImageTransportSurfaceOverlayMac::CheckPendingSwapsCallback, - weak_factory_.GetWeakPtr())); - } + // Reset all state for the next frame. + latency_info_.clear(); + pending_ca_layer_tree_.reset(); + pending_partial_damage_tree_.reset(); + return gfx::SwapResult::SWAP_ACK; } gfx::SwapResult ImageTransportSurfaceOverlayMac::SwapBuffers() { @@ -453,14 +263,6 @@ return true; } -bool ImageTransportSurfaceOverlayMac::SetBackbufferAllocation(bool allocated) { - if (!allocated) { - DisplayAndClearAllPendingSwaps(); - last_swap_time_ = base::TimeTicks(); - } - return true; -} - bool ImageTransportSurfaceOverlayMac::ScheduleOverlayPlane( int z_order, gfx::OverlayTransform transform, @@ -518,7 +320,6 @@ float scale_factor, bool has_alpha) { // Flush through any pending frames. - DisplayAndClearAllPendingSwaps(); pixel_size_ = pixel_size; scale_factor_ = scale_factor; return true; @@ -546,18 +347,4 @@ FROM_HERE, base::Bind(&IOSurfaceContextNoOp, context_on_new_gpu)); } -base::TimeTicks ImageTransportSurfaceOverlayMac::GetNextVSyncTimeAfter( - const base::TimeTicks& from, double interval_fraction) { - if (!vsync_parameters_valid_) - return from; - - // Compute the previous vsync time. - base::TimeTicks previous_vsync = - vsync_interval_ * ((from - vsync_timebase_) / vsync_interval_) + - vsync_timebase_; - - // Return |interval_fraction| through the next vsync. - return previous_vsync + (1 + interval_fraction) * vsync_interval_; -} - } // namespace gpu