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

Unified Diff: content/common/gpu/image_transport_surface_calayer_mac.mm

Issue 516643002: Fix assorted issues with remote CoreAnimation (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@clean_up_accel_layers
Patch Set: Incorporate review feedback Created 6 years, 4 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
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 ed8d3535cb9b26b90db5ac9d441c9a77c6a1e124..7531297ece8d113cb366b8fbc4a922d835efcde4 100644
--- a/content/common/gpu/image_transport_surface_calayer_mac.mm
+++ b/content/common/gpu/image_transport_surface_calayer_mac.mm
@@ -4,10 +4,13 @@
#include "content/common/gpu/image_transport_surface_calayer_mac.h"
+#include "base/command_line.h"
#include "base/mac/sdk_forward_declarations.h"
#include "content/common/gpu/surface_handle_types_mac.h"
#include "ui/base/cocoa/animation_utils.h"
#include "ui/gfx/geometry/size_conversions.h"
+#include "ui/gl/gl_gl_api_implementation.h"
+#include "ui/gl/gl_switches.h"
@interface ImageTransportLayer : CAOpenGLLayer {
content::CALayerStorageProvider* storageProvider_;
@@ -26,6 +29,8 @@
}
- (void)resetStorageProvider {
+ if (storageProvider_)
+ storageProvider_->LayerResetStorageProvider();
storageProvider_ = NULL;
}
@@ -60,6 +65,10 @@
pixelFormat:(CGLPixelFormatObj)pixelFormat
forLayerTime:(CFTimeInterval)timeInterval
displayTime:(const CVTimeStamp*)timeStamp {
+ // While in this callback, CoreAnimation has set |glContext| to be current.
+ // Ensure that the GL calls that we make are made against the native GL API.
+ gfx::ScopedSetGLToRealGLApi scoped_set_gl_api;
+
if (storageProvider_) {
storageProvider_->LayerDoDraw();
} else {
@@ -79,17 +88,13 @@ namespace content {
CALayerStorageProvider::CALayerStorageProvider(
ImageTransportSurfaceFBO* transport_surface)
: transport_surface_(transport_surface),
+ gpu_vsync_disabled_(CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableGpuVsync)),
has_pending_draw_(false),
can_draw_returned_false_count_(0),
- fbo_texture_(0) {
- // Allocate a CAContext to use to transport the CALayer to the browser
- // process.
- base::scoped_nsobject<NSDictionary> dict([[NSDictionary alloc] init]);
- CGSConnectionID connection_id = CGSMainConnectionID();
- context_.reset([CAContext contextWithCGSConnection:connection_id
- options:dict]);
- [context_ retain];
-}
+ fbo_texture_(0),
+ fbo_scale_factor_(1),
+ weak_factory_(this) {}
CALayerStorageProvider::~CALayerStorageProvider() {
}
@@ -126,15 +131,12 @@ bool CALayerStorageProvider::AllocateColorBufferStorage(
// Disable the fade-in animation as the layer is changed.
ScopedCAActionDisabler disabler;
- // Allocate a CALayer to draw texture into.
+ // Set the parameters that will be used to allocate the CALayer to draw the
+ // texture into.
share_group_context_.reset(CGLRetainContext(context));
fbo_texture_ = texture;
fbo_pixel_size_ = pixel_size;
- layer_.reset([[ImageTransportLayer alloc] initWithStorageProvider:this]);
- gfx::Size dip_size(gfx::ToFlooredSize(gfx::ScaleSize(
- fbo_pixel_size_, 1.0f / scale_factor)));
- [layer_ setContentsScale:scale_factor];
- [layer_ setFrame:CGRectMake(0, 0, dip_size.width(), dip_size.height())];
+ fbo_scale_factor_ = scale_factor;
return true;
}
@@ -155,25 +157,78 @@ void CALayerStorageProvider::FreeColorBufferStorage() {
fbo_pixel_size_ = gfx::Size();
}
-uint64 CALayerStorageProvider::GetSurfaceHandle() const {
- return SurfaceHandleFromCAContextID([context_ contextId]);
-}
-
-void CALayerStorageProvider::WillSwapBuffers() {
+void CALayerStorageProvider::SwapBuffers(
+ const gfx::Size& size, float scale_factor) {
DCHECK(!has_pending_draw_);
has_pending_draw_ = true;
- // Don't add the layer to the CAContext until a SwapBuffers is going to be
- // called, because the texture does not have any content until the
- // SwapBuffers call is about to be made.
- if ([context_ layer] != layer_.get())
+ // Allocate a CAContext to use to transport the CALayer to the browser
+ // process.
+ if (!context_) {
+ base::scoped_nsobject<NSDictionary> dict([[NSDictionary alloc] init]);
+ CGSConnectionID connection_id = CGSMainConnectionID();
+ context_.reset([CAContext contextWithCGSConnection:connection_id
+ options:dict]);
+ [context_ retain];
+ }
+
+ // Allocate a CALayer to use to draw the content.
+ if (!layer_) {
+ layer_.reset([[ImageTransportLayer alloc] initWithStorageProvider:this]);
+ gfx::Size dip_size(gfx::ToFlooredSize(gfx::ScaleSize(
+ fbo_pixel_size_, 1.0f / fbo_scale_factor_)));
+ [layer_ setContentsScale:fbo_scale_factor_];
+ [layer_ setFrame:CGRectMake(0, 0, dip_size.width(), dip_size.height())];
+
+ // Make the CALayer current to the CAContext and display its contents
+ // immediately.
[context_ setLayer:layer_];
+ }
- if (![layer_ isAsynchronous])
- [layer_ setAsynchronous:YES];
+ // 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();
+ } else {
+ if (![layer_ isAsynchronous])
+ [layer_ setAsynchronous:YES];
+ }
}
-void CALayerStorageProvider::CanFreeSwappedBuffer() {
+void CALayerStorageProvider::DrawWithVsyncDisabled() {
+ DCHECK(has_pending_draw_);
+ [layer_ setNeedsDisplay];
+
+ // 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));
+ }
+}
+
+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.
+}
+
+void CALayerStorageProvider::DiscardBackbuffer() {
+ // If this surface's backbuffer is discarded, it is because this surface has
+ // been made non-visible. Ensure that the previous contents are not briefly
+ // flashed when this is made visible by creating a new CALayer and CAContext
+ // at the next swap.
+ [layer_ resetStorageProvider];
+ layer_.reset();
+ context_.reset();
+}
+
+void CALayerStorageProvider::SwapBuffersAckedByBrowser() {
}
CGLContextObj CALayerStorageProvider::LayerShareGroupContext() {
@@ -185,20 +240,22 @@ bool CALayerStorageProvider::LayerCanDraw() {
can_draw_returned_false_count_ = 0;
return true;
} else {
- if (can_draw_returned_false_count_ == 30) {
- if ([layer_ isAsynchronous])
+ if ([layer_ isAsynchronous]) {
+ DCHECK(!gpu_vsync_disabled_);
+ // If we are in asynchronous mode, we will be getting callbacks at every
+ // vsync, asking us if we have anything to draw. If we get 30 of these in
+ // a row, ask that we stop getting these callback for now, so that we
+ // don't waste CPU cycles.
+ if (can_draw_returned_false_count_ == 30)
[layer_ setAsynchronous:NO];
- } else {
- can_draw_returned_false_count_ += 1;
+ else
+ can_draw_returned_false_count_ += 1;
}
return false;
}
}
void CALayerStorageProvider::LayerDoDraw() {
- DCHECK(has_pending_draw_);
- has_pending_draw_ = false;
-
GLint viewport[4] = {0, 0, 0, 0};
glGetIntegerv(GL_VIEWPORT, viewport);
gfx::Size viewport_size(viewport[2], viewport[3]);
@@ -233,7 +290,25 @@ void CALayerStorageProvider::LayerDoDraw() {
glDisable(GL_TEXTURE_RECTANGLE_ARB);
// Allow forward progress in the context now that the swap is complete.
- transport_surface_->UnblockContextAfterPendingSwap();
+ DCHECK(has_pending_draw_);
+ SendPendingSwapToBrowserAfterFrameDrawn();
+}
+
+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();
+}
+
+void CALayerStorageProvider::SendPendingSwapToBrowserAfterFrameDrawn() {
+ if (!has_pending_draw_)
+ return;
+ weak_factory_.InvalidateWeakPtrs();
+ has_pending_draw_ = false;
+ transport_surface_->SendSwapBuffers(
+ SurfaceHandleFromCAContextID([context_ contextId]),
+ fbo_pixel_size_,
+ fbo_scale_factor_);
}
} // namespace content

Powered by Google App Engine
This is Rietveld 408576698