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

Unified Diff: gpu/ipc/service/image_transport_surface_overlay_mac.mm

Issue 1867163002: Mac: Clean up ImageTransportSurfaceOverlayMac timing (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 4 years, 8 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
« no previous file with comments | « gpu/ipc/service/image_transport_surface_overlay_mac.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
« no previous file with comments | « gpu/ipc/service/image_transport_surface_overlay_mac.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698