| Index: content/common/gpu/image_transport_surface_calayer_mac.mm
|
| diff --git a/content/common/gpu/image_transport_surface_calayer_mac.mm b/content/common/gpu/image_transport_surface_calayer_mac.mm
|
| index 7531297ece8d113cb366b8fbc4a922d835efcde4..37354607502d3de3dd67f1832110acf6ec7212e7 100644
|
| --- a/content/common/gpu/image_transport_surface_calayer_mac.mm
|
| +++ b/content/common/gpu/image_transport_surface_calayer_mac.mm
|
| @@ -90,11 +90,12 @@ CALayerStorageProvider::CALayerStorageProvider(
|
| : transport_surface_(transport_surface),
|
| gpu_vsync_disabled_(CommandLine::ForCurrentProcess()->HasSwitch(
|
| switches::kDisableGpuVsync)),
|
| + throttling_disabled_(false),
|
| has_pending_draw_(false),
|
| can_draw_returned_false_count_(0),
|
| fbo_texture_(0),
|
| fbo_scale_factor_(1),
|
| - weak_factory_(this) {}
|
| + pending_draw_weak_factory_(this) {}
|
|
|
| CALayerStorageProvider::~CALayerStorageProvider() {
|
| }
|
| @@ -141,20 +142,15 @@ bool CALayerStorageProvider::AllocateColorBufferStorage(
|
| }
|
|
|
| void CALayerStorageProvider::FreeColorBufferStorage() {
|
| - // We shouldn't be asked to free a texture when we still have yet to draw it.
|
| - DCHECK(!has_pending_draw_);
|
| - has_pending_draw_ = false;
|
| - can_draw_returned_false_count_ = 0;
|
| -
|
| // Note that |context_| still holds a reference to |layer_|, and will until
|
| // a new frame is swapped in.
|
| - [layer_ displayIfNeeded];
|
| [layer_ resetStorageProvider];
|
| layer_.reset();
|
|
|
| share_group_context_.reset();
|
| fbo_texture_ = 0;
|
| fbo_pixel_size_ = gfx::Size();
|
| + can_draw_returned_false_count_ = 0;
|
| }
|
|
|
| void CALayerStorageProvider::SwapBuffers(
|
| @@ -185,37 +181,41 @@ void CALayerStorageProvider::SwapBuffers(
|
| [context_ setLayer:layer_];
|
| }
|
|
|
| - // Tell CoreAnimation to draw our frame. We will send the IPC to the browser
|
| - // when CoreAnimation has drawn our frame.
|
| - if (gpu_vsync_disabled_) {
|
| - DrawWithVsyncDisabled();
|
| + // Tell CoreAnimation to draw our frame.
|
| + if (gpu_vsync_disabled_ || throttling_disabled_) {
|
| + DrawImmediatelyAndUnblockBrowser();
|
| } else {
|
| if (![layer_ isAsynchronous])
|
| [layer_ setAsynchronous:YES];
|
| +
|
| + // If CoreAnimation doesn't end up drawing our frame, un-block the browser
|
| + // after a timeout of 1/6th of a second has passed.
|
| + base::MessageLoop::current()->PostDelayedTask(
|
| + FROM_HERE,
|
| + base::Bind(&CALayerStorageProvider::DrawImmediatelyAndUnblockBrowser,
|
| + pending_draw_weak_factory_.GetWeakPtr()),
|
| + base::TimeDelta::FromSeconds(1) / 6);
|
| }
|
| }
|
|
|
| -void CALayerStorageProvider::DrawWithVsyncDisabled() {
|
| - DCHECK(has_pending_draw_);
|
| +void CALayerStorageProvider::DrawImmediatelyAndUnblockBrowser() {
|
| + CHECK(has_pending_draw_);
|
| + if ([layer_ isAsynchronous])
|
| + [layer_ setAsynchronous:NO];
|
| [layer_ setNeedsDisplay];
|
| + [layer_ displayIfNeeded];
|
|
|
| - // Sometimes, setNeedsDisplay calls are dropped on the floor. Make this not
|
| - // hang the renderer by re-issuing the call if the draw has not yet
|
| - // happened.
|
| - if (has_pending_draw_) {
|
| - // Delay sending another draw immediately to avoid starving the run loop.
|
| - base::MessageLoop::current()->PostDelayedTask(
|
| - FROM_HERE,
|
| - base::Bind(&CALayerStorageProvider::DrawWithVsyncDisabled,
|
| - weak_factory_.GetWeakPtr()),
|
| - base::TimeDelta::FromMilliseconds(5));
|
| - }
|
| + // Sometimes, the setNeedsDisplay+displayIfNeeded pairs have no effect. This
|
| + // can happen if the NSView that this layer is attached to isn't in the
|
| + // window hierarchy (e.g, tab capture of a backgrounded tab). In this case,
|
| + // the frame will never be seen, so drop it.
|
| + UnblockBrowserIfNeeded();
|
| }
|
|
|
| void CALayerStorageProvider::WillWriteToBackbuffer() {
|
| - // TODO(ccameron): The browser may need to continue issuing swaps even when
|
| - // they do not draw. In these cases it is necessary to either double-buffer
|
| - // the resulting texture, or to drop frames.
|
| + // The browser will always throttle itself so that there is no pending draw
|
| + // when this output surface is written to.
|
| + DCHECK(!has_pending_draw_);
|
| }
|
|
|
| void CALayerStorageProvider::DiscardBackbuffer() {
|
| @@ -228,7 +228,9 @@ void CALayerStorageProvider::DiscardBackbuffer() {
|
| context_.reset();
|
| }
|
|
|
| -void CALayerStorageProvider::SwapBuffersAckedByBrowser() {
|
| +void CALayerStorageProvider::SwapBuffersAckedByBrowser(
|
| + bool disable_throttling) {
|
| + throttling_disabled_ = disable_throttling;
|
| }
|
|
|
| CGLContextObj CALayerStorageProvider::LayerShareGroupContext() {
|
| @@ -290,20 +292,19 @@ void CALayerStorageProvider::LayerDoDraw() {
|
| glDisable(GL_TEXTURE_RECTANGLE_ARB);
|
|
|
| // Allow forward progress in the context now that the swap is complete.
|
| - DCHECK(has_pending_draw_);
|
| - SendPendingSwapToBrowserAfterFrameDrawn();
|
| + UnblockBrowserIfNeeded();
|
| }
|
|
|
| void CALayerStorageProvider::LayerResetStorageProvider() {
|
| // If we are providing back-pressure by waiting for a draw, that draw will
|
| // now never come, so release the pressure now.
|
| - SendPendingSwapToBrowserAfterFrameDrawn();
|
| + UnblockBrowserIfNeeded();
|
| }
|
|
|
| -void CALayerStorageProvider::SendPendingSwapToBrowserAfterFrameDrawn() {
|
| +void CALayerStorageProvider::UnblockBrowserIfNeeded() {
|
| if (!has_pending_draw_)
|
| return;
|
| - weak_factory_.InvalidateWeakPtrs();
|
| + pending_draw_weak_factory_.InvalidateWeakPtrs();
|
| has_pending_draw_ = false;
|
| transport_surface_->SendSwapBuffers(
|
| SurfaceHandleFromCAContextID([context_ contextId]),
|
|
|