| Index: gpu/ipc/service/image_transport_surface_overlay_mac.mm
|
| diff --git a/gpu/ipc/service/image_transport_surface_overlay_mac.mm b/gpu/ipc/service/image_transport_surface_overlay_mac.mm
|
| index 4eea4a1bf53962e431654272bad6d0f74c777677..876b23edf376fe18376f041b9d8aa2be01295e1e 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 @@ typedef void* GLeglImageOES;
|
|
|
| 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 @@ void IOSurfaceContextNoOp(scoped_refptr<ui::IOSurfaceContext>) {
|
|
|
| } // namespace
|
|
|
| -@interface CALayer(Private)
|
| --(void)setContentsChanged;
|
| -@end
|
| -
|
| namespace gpu {
|
|
|
| scoped_refptr<gfx::GLSurface> ImageTransportSurfaceCreateNativeSurface(
|
| @@ -86,33 +63,6 @@ scoped_refptr<gfx::GLSurface> ImageTransportSurfaceCreateNativeSurface(
|
| 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 @@ ImageTransportSurfaceOverlayMac::ImageTransportSurfaceOverlayMac(
|
| 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 @@ bool ImageTransportSurfaceOverlayMac::Initialize(
|
| }
|
|
|
| void ImageTransportSurfaceOverlayMac::Destroy() {
|
| - DisplayAndClearAllPendingSwaps();
|
| -
|
| current_partial_damage_tree_.reset();
|
| current_ca_layer_tree_.reset();
|
| }
|
| @@ -220,130 +166,33 @@ gfx::SwapResult ImageTransportSurfaceOverlayMac::SwapBuffersInternal(
|
| 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");
|
| - }
|
| -
|
| - // 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");
|
| + TRACE_EVENT0("gpu", "ImageTransportSurfaceOverlayMac::glFinish");
|
| + CheckGLErrors("Before finish");
|
| + glFinish();
|
| + CheckGLErrors("After finish");
|
| }
|
| - 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 @@ void ImageTransportSurfaceOverlayMac::DisplayFirstPendingSwapImmediately() {
|
| 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 @@ void ImageTransportSurfaceOverlayMac::DisplayFirstPendingSwapImmediately() {
|
| 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));
|
| -
|
| - // 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()));
|
| - }
|
| + SendAcceleratedSurfaceBuffersSwapped(handle_, ca_context_id, io_surface,
|
| + pixel_size_, scale_factor_,
|
| + std::move(latency_info_));
|
| +
|
| + // 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 @@ bool ImageTransportSurfaceOverlayMac::OnMakeCurrent(gfx::GLContext* context) {
|
| 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 @@ bool ImageTransportSurfaceOverlayMac::Resize(const gfx::Size& pixel_size,
|
| 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 @@ void ImageTransportSurfaceOverlayMac::OnGpuSwitched() {
|
| 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
|
|
|