Bug 1491442 - Disable all non-CoreAnimation rendering paths when gfx.core-animation.enabled is set. r=mattwoodrow
authorMarkus Stange <mstange@themasta.com>
Fri, 16 Aug 2019 01:12:18 +0000
changeset 488407 e89c3a6b2cd8eb8c8c328b86433765217ee7684e
parent 488406 9ffcdc648de567afa343e025298a2e2a424e7512
child 488408 372c720b6ce81374cfca793c8ee4e0c9cade03b2
push id36443
push userccoroiu@mozilla.com
push dateFri, 16 Aug 2019 09:48:15 +0000
treeherdermozilla-central@5d4cbfe103bb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1491442
milestone70.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1491442 - Disable all non-CoreAnimation rendering paths when gfx.core-animation.enabled is set. r=mattwoodrow This patch leaves you with empty windows everywhere. We will build the new rendering paths from the ground up in the upcoming patches. Differential Revision: https://phabricator.services.mozilla.com/D38754
widget/cocoa/nsChildView.h
widget/cocoa/nsChildView.mm
--- a/widget/cocoa/nsChildView.h
+++ b/widget/cocoa/nsChildView.h
@@ -154,26 +154,28 @@ class WidgetRenderingContext;
   // last received event so that, when we receive one of the events, we make sure
   // to send its pair event first, in case we didn't yet for any reason.
   BOOL mExpectingWheelStop;
 
   // Set to YES when our GL surface has been updated and we need to call
   // updateGLContext on the compositor thread before we composite.
   // Accesses from different threads are synchronized via mGLContext's
   // CGLContextObj lock.
+  // Always NO if StaticPrefs::gfx_core_animation_enabled_AtStartup() is true.
   BOOL mNeedsGLUpdate;
 
   // Holds our drag service across multiple drag calls. The reference to the
   // service is obtained when the mouse enters the view and is released when
   // the mouse exits or there is a drop. This prevents us from having to
   // re-establish the connection to the service manager many times per second
   // when handling |draggingUpdated:| messages.
   nsIDragService* mDragService;
 
   // The NSOpenGLContext that is attached to our mPixelHostingView.
+  // Always null if StaticPrefs::gfx_core_animation_enabled_AtStartup() is true.
   NSOpenGLContext* mGLContext;
 
   // Gestures support
   //
   // mGestureState is used to detect when Cocoa has called both
   // magnifyWithEvent and rotateWithEvent within the same
   // beginGestureWithEvent and endGestureWithEvent sequence. We
   // discard the spurious gesture event so as not to confuse Gecko.
@@ -199,27 +201,28 @@ class WidgetRenderingContext;
   BOOL* mCancelSwipeAnimation;
 #endif
 
   // Whether this uses off-main-thread compositing.
   BOOL mUsingOMTCompositor;
 
   // The mask image that's used when painting into the titlebar using basic
   // CGContext painting (i.e. non-accelerated).
+  // Always null if StaticPrefs::gfx_core_animation_enabled_AtStartup() is true.
   CGImageRef mTopLeftCornerMask;
 
   // Subviews of self, which act as container views for vibrancy views and
   // non-draggable views.
   NSView* mVibrancyViewsContainer;      // [STRONG]
   NSView* mNonDraggableViewsContainer;  // [STRONG]
 
   // The view that does our drawing. Always non-null.
-  // This is a subview of self so that it can be ordered on top of
-  // mVibrancyViewsContainer. Drawing in this view can be performed in different
-  // ways:
+  // This is a subview of self so that it can be ordered on top of mVibrancyViewsContainer.
+  // Drawing in this view can be performed in different ways:
+  // If StaticPrefs::gfx_core_animation_enabled_AtStartup() is false, there are two cases:
   // If mUsingOMTCompositor is false, drawing is performed on the main thread
   // inside the view's drawRect handler. If mUsingOMTCompositor is true,
   // mGLContext will be non-null and will be associated with mPixelHostingView,
   // and rendering will be performed on the compositor thread into mGLContext's
   // primary framebuffer.
   PixelHostingView* mPixelHostingView;
 
   // Last pressure stage by trackpad's force click
@@ -647,23 +650,25 @@ class nsChildView final : public nsBaseW
   bool mVisible;
   bool mDrawing;
   bool mIsDispatchPaint;  // Is a paint event being dispatched
 
   bool mPluginFocused;
 
   // Used in BasicCompositor OMTC mode. Presents the BasicCompositor result
   // surface to the screen using an OpenGL context.
+  // Always null if StaticPrefs::gfx_core_animation_enabled_AtStartup() is true.
   mozilla::UniquePtr<GLPresenter> mGLPresenter;
 
   mozilla::UniquePtr<mozilla::VibrancyManager> mVibrancyManager;
   RefPtr<mozilla::SwipeTracker> mSwipeTracker;
   mozilla::UniquePtr<mozilla::SwipeEventQueue> mSwipeEventQueue;
 
   // Only used for drawRect-based painting in popups.
+  // Always null if StaticPrefs::gfx_core_animation_enabled_AtStartup() is true.
   RefPtr<mozilla::gfx::DrawTarget> mBackingSurface;
 
   // This flag is only used when APZ is off. It indicates that the current pan
   // gesture was processed as a swipe. Sometimes the swipe animation can finish
   // before momentum events of the pan gesture have stopped firing, so this
   // flag tells us that we shouldn't allow the remaining events to cause
   // scrolling. It is reset to false once a new gesture starts (as indicated by
   // a PANGESTURE_(MAY)START event).
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -244,17 +244,18 @@ static NSMutableDictionary* sNativeKeyEv
 // Flips a screen coordinate from a point in the cocoa coordinate system (bottom-left rect) to a
 // point that is a "flipped" cocoa coordinate system (starts in the top-left).
 static inline void FlipCocoaScreenCoordinate(NSPoint& inPoint) {
   inPoint.y = nsCocoaUtils::FlippedScreenY(inPoint.y);
 }
 
 namespace {
 
-// Used for OpenGL drawing from the compositor thread for BasicCompositor OMTC.
+// Used for OpenGL drawing from the compositor thread for BasicCompositor OMTC
+// when StaticPrefs::gfx_core_animation_enabled_AtStartup() is false.
 // This was created at a time when we didn't know how to use CoreAnimation for
 // robust off-main-thread drawing.
 class GLPresenter : public GLManager {
  public:
   static mozilla::UniquePtr<GLPresenter> CreateForWindow(nsIWidget* aWindow) {
     // Contrary to CompositorOGL, we allow unaccelerated OpenGL contexts to be
     // used. BasicCompositor only requires very basic GL functionality.
     bool forWebRender = false;
@@ -1345,16 +1346,18 @@ bool nsChildView::PaintWindowInDrawTarge
     // We only need this so that we actually get DidPaintWindow fired
     return PaintWindow(aRegion);
   }
   return false;
 }
 
 bool nsChildView::PaintWindowInContext(CGContextRef aContext, const LayoutDeviceIntRegion& aRegion,
                                        gfx::IntSize aSurfaceSize) {
+  MOZ_RELEASE_ASSERT(!StaticPrefs::gfx_core_animation_enabled_AtStartup());
+
   if (!mBackingSurface || mBackingSurface->GetSize() != aSurfaceSize) {
     mBackingSurface = gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
         aSurfaceSize, gfx::SurfaceFormat::B8G8R8A8);
     if (!mBackingSurface) {
       return false;
     }
   }
 
@@ -1816,16 +1819,21 @@ bool nsChildView::PreRender(WidgetRender
     return false;
   }
   return true;
 }
 
 bool nsChildView::PreRenderImpl(WidgetRenderingContext* aContext) {
   UniquePtr<GLManager> manager(GLManager::CreateGLManager(aContext->mLayerManager));
   gl::GLContext* gl = manager ? manager->gl() : aContext->mGL;
+
+  if (StaticPrefs::gfx_core_animation_enabled_AtStartup()) {
+    return false;  // This will be fleshed out in upcoming patches.
+  }
+
   if (gl) {
     return [mView preRender:GLContextCGL::Cast(gl)->GetNSOpenGLContext()];
   }
 
   // BasicCompositor.
   MOZ_RELEASE_ASSERT(mGLPresenter, "Should have been set up in InitCompositor");
   if (![mView preRender:mGLPresenter->GetNSOpenGLContext()]) {
     return false;
@@ -2357,27 +2365,30 @@ void nsChildView::EndRemoteDrawing() {
 void nsChildView::CleanupRemoteDrawing() {
   mBasicCompositorImage = nullptr;
   mCornerMaskImage = nullptr;
   mTitlebarImage = nullptr;
   mGLPresenter = nullptr;
 }
 
 bool nsChildView::InitCompositor(Compositor* aCompositor) {
-  if (aCompositor->GetBackendType() == LayersBackend::LAYERS_BASIC) {
+  if (!StaticPrefs::gfx_core_animation_enabled_AtStartup() &&
+      aCompositor->GetBackendType() == LayersBackend::LAYERS_BASIC) {
     if (!mGLPresenter) {
       mGLPresenter = GLPresenter::CreateForWindow(this);
     }
 
     return !!mGLPresenter;
   }
   return true;
 }
 
 void nsChildView::DoRemoteComposition(const LayoutDeviceIntRect& aRenderRect) {
+  MOZ_RELEASE_ASSERT(!StaticPrefs::gfx_core_animation_enabled_AtStartup());
+
   mGLPresenter->BeginFrame(aRenderRect.Size());
 
   // Draw the result from the basic compositor.
   mBasicCompositorImage->Draw(mGLPresenter.get(), LayoutDeviceIntPoint(0, 0));
 
   // DrawWindowOverlay doesn't do anything for non-GL, so it didn't paint
   // anything during the basic compositor transaction. Draw the overlay now.
   DrawWindowOverlay(mGLPresenter.get(), aRenderRect);
@@ -2923,20 +2934,23 @@ NSEvent* gLastDragMouseDownEvent = nil;
                                                name:NSPreferredScrollerStyleDidChangeNotification
                                              object:nil];
   [[NSDistributedNotificationCenter defaultCenter]
              addObserver:self
                 selector:@selector(systemMetricsChanged)
                     name:@"AppleAquaScrollBarVariantChanged"
                   object:nil
       suspensionBehavior:NSNotificationSuspensionBehaviorDeliverImmediately];
-  [[NSNotificationCenter defaultCenter] addObserver:self
-                                           selector:@selector(_surfaceNeedsUpdate:)
-                                               name:NSViewGlobalFrameDidChangeNotification
-                                             object:mPixelHostingView];
+
+  if (!StaticPrefs::gfx_core_animation_enabled_AtStartup()) {
+    [[NSNotificationCenter defaultCenter] addObserver:self
+                                             selector:@selector(_surfaceNeedsUpdate:)
+                                                 name:NSViewGlobalFrameDidChangeNotification
+                                               object:mPixelHostingView];
+  }
 
   [[NSDistributedNotificationCenter defaultCenter]
              addObserver:self
                 selector:@selector(systemMetricsChanged)
                     name:@"AppleInterfaceThemeChangedNotification"
                   object:nil
       suspensionBehavior:NSNotificationSuspensionBehaviorDeliverImmediately];
 
@@ -2978,16 +2992,18 @@ NSEvent* gLastDragMouseDownEvent = nil;
 
 - (void)uninstallTextInputHandler {
   mTextInputHandler = nullptr;
 }
 
 - (bool)preRender:(NSOpenGLContext*)aGLContext {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
 
+  MOZ_RELEASE_ASSERT(!StaticPrefs::gfx_core_animation_enabled_AtStartup());
+
   if (![self window] || ([[self window] isKindOfClass:[BaseWindow class]] &&
                          ![(BaseWindow*)[self window] isVisibleOrBeingShown] &&
                          ![(BaseWindow*)[self window] isMiniaturized])) {
     // Before the window is shown, our GL context's front FBO is not
     // framebuffer complete, so we refuse to render.
     return false;
   }
 
@@ -3123,22 +3139,27 @@ NSEvent* gLastDragMouseDownEvent = nil;
 - (BOOL)mouseDownCanMoveWindow {
   // Return YES so that parts of this view can be draggable. The non-draggable
   // parts will be covered by NSViews that return NO from
   // mouseDownCanMoveWindow and thus override draggability from the inside.
   // These views are assembled in nsChildView::UpdateWindowDraggingRegion.
   return YES;
 }
 
+// Only called if StaticPrefs::gfx_core_animation_enabled_AtStartup() is false.
 - (void)updateGLContext {
+  MOZ_RELEASE_ASSERT(!StaticPrefs::gfx_core_animation_enabled_AtStartup());
+
   [mGLContext setView:mPixelHostingView];
   [mGLContext update];
 }
 
 - (void)_surfaceNeedsUpdate:(NSNotification*)notification {
+  MOZ_RELEASE_ASSERT(!StaticPrefs::gfx_core_animation_enabled_AtStartup());
+
   if (mGLContext) {
     CGLLockContext((CGLContextObj)[mGLContext CGLContextObj]);
     mNeedsGLUpdate = YES;
     CGLUnlockContext((CGLContextObj)[mGLContext CGLContextObj]);
   }
 }
 
 - (void)viewDidChangeBackingProperties {
@@ -3180,16 +3201,18 @@ NSEvent* gLastDragMouseDownEvent = nil;
 - (NSColor*)vibrancyFillColorForThemeGeometryType:(nsITheme::ThemeGeometryType)aThemeGeometryType {
   if (!mGeckoChild) {
     return [NSColor whiteColor];
   }
   return mGeckoChild->VibrancyFillColorForThemeGeometryType(aThemeGeometryType);
 }
 
 - (LayoutDeviceIntRegion)nativeDirtyRegionWithBoundingRect:(NSRect)aRect {
+  MOZ_RELEASE_ASSERT(!StaticPrefs::gfx_core_animation_enabled_AtStartup());
+
   LayoutDeviceIntRect boundingRect = mGeckoChild->CocoaPointsToDevPixels(aRect);
   const NSRect* rects;
   NSInteger count;
   [mPixelHostingView getRectsBeingDrawn:&rects count:&count];
 
   if (count > MAX_RECTS_IN_REGION) {
     return boundingRect;
   }
@@ -3200,17 +3223,20 @@ NSEvent* gLastDragMouseDownEvent = nil;
   }
   region.And(region, boundingRect);
   return region;
 }
 
 // The display system has told us that a portion of our view is dirty. Tell
 // gecko to paint it
 // This method is called from mPixelHostingView's drawRect handler.
+// Only called when StaticPrefs::gfx_core_animation_enabled_AtStartup() is false.
 - (void)doDrawRect:(NSRect)aRect {
+  MOZ_RELEASE_ASSERT(!StaticPrefs::gfx_core_animation_enabled_AtStartup());
+
   if (!NS_IsMainThread()) {
     // In the presence of CoreAnimation, this method can sometimes be called on
     // a non-main thread. Ignore those calls because Gecko can only react to
     // them on the main thread.
     return;
   }
 
   if (!mGeckoChild || !mGeckoChild->IsVisible()) return;
@@ -3268,27 +3294,31 @@ NSEvent* gLastDragMouseDownEvent = nil;
 
 - (CGFloat)cornerRadius {
   NSView* frameView = [[[self window] contentView] superview];
   if (!frameView || ![frameView respondsToSelector:@selector(roundedCornerRadius)]) return 4.0f;
   return [frameView roundedCornerRadius];
 }
 
 - (void)setGLOpaque:(BOOL)aOpaque {
-  CGLLockContext((CGLContextObj)[mGLContext CGLContextObj]);
-  // Make the context opaque for fullscreen (since it performs better), and transparent
-  // for windowed (since we need it for rounded corners), but allow overriding
-  // it to opaque for testing purposes, even if that breaks the rounded corners.
-  GLint opaque = aOpaque || StaticPrefs::gfx_compositor_glcontext_opaque();
-  [mGLContext setValues:&opaque forParameter:NSOpenGLCPSurfaceOpacity];
-  CGLUnlockContext((CGLContextObj)[mGLContext CGLContextObj]);
-}
-
-// Our "accelerated" windows are NSWindows which are not CoreAnimation-backed
-// but contain an NSView with an attached NSOpenGLContext.
+  if (mGLContext) {
+    MOZ_RELEASE_ASSERT(!StaticPrefs::gfx_core_animation_enabled_AtStartup());
+    CGLLockContext((CGLContextObj)[mGLContext CGLContextObj]);
+    // Make the context opaque for fullscreen (since it performs better), and transparent
+    // for windowed (since we need it for rounded corners), but allow overriding
+    // it to opaque for testing purposes, even if that breaks the rounded corners.
+    GLint opaque = aOpaque || StaticPrefs::gfx_compositor_glcontext_opaque();
+    [mGLContext setValues:&opaque forParameter:NSOpenGLCPSurfaceOpacity];
+    CGLUnlockContext((CGLContextObj)[mGLContext CGLContextObj]);
+  }
+}
+
+// If StaticPrefs::gfx_core_animation_enabled_AtStartup() is false, our "accelerated" windows are
+// NSWindows which are not CoreAnimation-backed but contain an NSView with
+// an attached NSOpenGLContext.
 // This means such windows have two WindowServer-level "surfaces" (NSSurface):
 //  (1) The window's "drawRect" contents (a main-memory backed buffer) in the
 //      back and
 //  (2) the OpenGL drawing in the front.
 // These two surfaces are composited by the window manager against our window's
 // backdrop, i.e. everything on the screen behind our window.
 // When our window has rounded corners, our OpenGL drawing respects those
 // rounded corners and will leave transparent pixels in the corners. In these
@@ -3383,16 +3413,20 @@ NSEvent* gLastDragMouseDownEvent = nil;
 - (void)viewWillDraw {
   if (!NS_IsMainThread()) {
     // In the presence of CoreAnimation, this method can sometimes be called on
     // a non-main thread. Ignore those calls because Gecko can only react to
     // them on the main thread.
     return;
   }
 
+  if (StaticPrefs::gfx_core_animation_enabled_AtStartup()) {
+    return;
+  }
+
   nsAutoRetainCocoaObject kungFuDeathGrip(self);
 
   if (mGeckoChild) {
     // The OS normally *will* draw our NSWindow, no matter what we do here.
     // But Gecko can delete our parent widget(s) (along with mGeckoChild)
     // while processing a paint request, which closes our NSWindow and
     // makes the OS throw an NSInternalInconsistencyException assertion when
     // it tries to draw it.  Sometimes the OS also aborts the browser process.
@@ -5894,16 +5928,19 @@ nsresult nsChildView::GetSelectionAsPlai
   return YES;
 }
 
 - (NSView*)hitTest:(NSPoint)aPoint {
   return nil;
 }
 
 - (void)drawRect:(NSRect)aRect {
+  if (StaticPrefs::gfx_core_animation_enabled_AtStartup()) {
+    return;
+  }
   [(ChildView*)[self superview] doDrawRect:aRect];
 }
 
 - (BOOL)wantsBestResolutionOpenGLSurface {
   return nsCocoaUtils::HiDPIEnabled() ? YES : NO;
 }
 
 @end