Bug 1594950 - Change NextSurface APIs to accept a dirty region, and remove the public method InvalidateRegionThroughoutSwapchain. r=jrmuizel
authorMarkus Stange <mstange@themasta.com>
Wed, 13 Nov 2019 18:55:18 +0000
changeset 501816 4391cb16bb0b291b02a1fc42a7295c564d76d9ec
parent 501815 2a2c01a5ce9a25fd52d55b56a1b238eebfc7d752
child 501817 25c597f8703fb05ceb531889a0a478bdebfd78fb
push id114172
push userdluca@mozilla.com
push dateTue, 19 Nov 2019 11:31:10 +0000
treeherdermozilla-inbound@b5c5ba07d3db [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs1594950
milestone72.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 1594950 - Change NextSurface APIs to accept a dirty region, and remove the public method InvalidateRegionThroughoutSwapchain. r=jrmuizel Differential Revision: https://phabricator.services.mozilla.com/D50878
gfx/layers/NativeLayer.h
gfx/layers/NativeLayerCA.h
gfx/layers/NativeLayerCA.mm
gfx/layers/basic/BasicCompositor.cpp
gfx/layers/composite/LayerManagerComposite.cpp
gfx/layers/opengl/CompositorOGL.cpp
gfx/webrender_bindings/RenderCompositorOGL.cpp
widget/cocoa/nsChildView.mm
--- a/gfx/layers/NativeLayer.h
+++ b/gfx/layers/NativeLayer.h
@@ -83,32 +83,28 @@ class NativeLayer {
   virtual void SetClipRect(const Maybe<gfx::IntRect>& aClipRect) = 0;
   virtual Maybe<gfx::IntRect> ClipRect() = 0;
 
   // Whether the surface contents are flipped vertically compared to this
   // layer's coordinate system. Can be set on any thread at any time.
   virtual void SetSurfaceIsFlipped(bool aIsFlipped) = 0;
   virtual bool SurfaceIsFlipped() = 0;
 
-  // Invalidates the specified region in all surfaces that are tracked by this
-  // layer.
-  virtual void InvalidateRegionThroughoutSwapchain(
-      const gfx::IntRegion& aRegion) = 0;
-
   // Returns a DrawTarget. The size of the DrawTarget will be the same as the
   // size of this layer. The caller should draw to that DrawTarget, then drop
   // its reference to the DrawTarget, and then call NotifySurfaceReady(). It can
   // limit its drawing to CurrentSurfaceInvalidRegion() (which is in the
   // DrawTarget's device space). After a call to NextSurface*, NextSurface* must
   // not be called again until after NotifySurfaceReady has been called. Can be
   // called on any thread. When used from multiple threads, callers need to make
   // sure that they still only call NextSurface* and NotifySurfaceReady
   // alternatingly and not in any other order.
+  // aUpdateRegion must not extend beyond the layer size.
   virtual RefPtr<gfx::DrawTarget> NextSurfaceAsDrawTarget(
-      gfx::BackendType aBackendType) = 0;
+      const gfx::IntRegion& aUpdateRegion, gfx::BackendType aBackendType) = 0;
 
   // Set the GLContext to use for the MozFramebuffer that are returned from
   // NextSurfaceAsFramebuffer. If changed to a different value, all
   // MozFramebuffers tracked by this layer will be discarded.
   // It's a good idea to call SetGLContext(nullptr) before destroying this
   // layer so that GL resource destruction happens at a good time and on the
   // right thread.
   virtual void SetGLContext(gl::GLContext* aGLContext) = 0;
@@ -126,25 +122,27 @@ class NativeLayer {
   // SetGLContext. The NativeLayer will keep a reference to the MozFramebuffer
   // so that it can reuse the same MozFramebuffer whenever it uses the same
   // underlying surface. Calling SetGLContext with a different context will
   // release that reference. After a call to NextSurface*, NextSurface* must not
   // be called again until after NotifySurfaceReady has been called. Can be
   // called on any thread. When used from multiple threads, callers need to make
   // sure that they still only call NextSurface and NotifySurfaceReady
   // alternatingly and not in any other order.
-  virtual Maybe<GLuint> NextSurfaceAsFramebuffer(bool aNeedsDepth) = 0;
+  // aUpdateRegion must not extend beyond the layer size.
+  virtual Maybe<GLuint> NextSurfaceAsFramebuffer(
+      const gfx::IntRegion& aUpdateRegion, bool aNeedsDepth) = 0;
 
   // The invalid region of the surface that has been returned from the most
   // recent call to NextSurface*. Newly-created surfaces are entirely invalid.
   // For surfaces that have been used before, the invalid region is the union of
-  // all invalid regions that have been passed to
-  // InvalidateRegionThroughoutSwapchain since the last time that
-  // NotifySurfaceReady was called for this surface. Can only be called between
-  // calls to NextSurface* and NotifySurfaceReady. Can be called on any thread.
+  // all invalid regions that have been passed to NextSurface* since the last
+  // time that NotifySurfaceReady was called for this surface. Can only be
+  // called between calls to NextSurface* and NotifySurfaceReady. Can be called
+  // on any thread.
   virtual gfx::IntRegion CurrentSurfaceInvalidRegion() = 0;
 
   // Indicates that the surface which has been returned from the most recent
   // call to NextSurface* is now finished being drawn to and can be displayed on
   // the screen. Resets the invalid region on the surface to the empty region.
   virtual void NotifySurfaceReady() = 0;
 
  protected:
--- a/gfx/layers/NativeLayerCA.h
+++ b/gfx/layers/NativeLayerCA.h
@@ -102,23 +102,23 @@ class NativeLayerCA : public NativeLayer
  public:
   virtual NativeLayerCA* AsNativeLayerCA() override { return this; }
 
   // Overridden methods
   gfx::IntSize GetSize() override;
   void SetPosition(const gfx::IntPoint& aPosition) override;
   gfx::IntPoint GetPosition() override;
   gfx::IntRect GetRect() override;
-  void InvalidateRegionThroughoutSwapchain(
-      const gfx::IntRegion& aRegion) override;
   RefPtr<gfx::DrawTarget> NextSurfaceAsDrawTarget(
+      const gfx::IntRegion& aUpdateRegion,
       gfx::BackendType aBackendType) override;
   void SetGLContext(gl::GLContext* aGLContext) override;
   gl::GLContext* GetGLContext() override;
-  Maybe<GLuint> NextSurfaceAsFramebuffer(bool aNeedsDepth) override;
+  Maybe<GLuint> NextSurfaceAsFramebuffer(const gfx::IntRegion& aUpdateRegion,
+                                         bool aNeedsDepth) override;
   gfx::IntRegion CurrentSurfaceInvalidRegion() override;
   void NotifySurfaceReady() override;
   bool IsOpaque() override;
   void SetClipRect(const Maybe<gfx::IntRect>& aClipRect) override;
   Maybe<gfx::IntRect> ClipRect() override;
   void SetSurfaceIsFlipped(bool aIsFlipped) override;
   bool SurfaceIsFlipped() override;
 
@@ -156,16 +156,21 @@ class NativeLayerCA : public NativeLayer
   // order.
   CFTypeRefPtr<IOSurfaceRef> NextSurface(const MutexAutoLock&);
 
   // To be called by NativeLayerRootCA:
   CALayer* UnderlyingCALayer() { return mWrappingCALayer; }
   void ApplyChanges();
   void SetBackingScale(float aBackingScale);
 
+  // Invalidates the specified region in all surfaces that are tracked by this
+  // layer.
+  void InvalidateRegionThroughoutSwapchain(const MutexAutoLock&,
+                                           const gfx::IntRegion& aRegion);
+
   GLuint GetOrCreateFramebufferForSurface(const MutexAutoLock&,
                                           CFTypeRefPtr<IOSurfaceRef> aSurface,
                                           bool aNeedsDepth);
 
   struct SurfaceWithInvalidRegion {
     CFTypeRefPtr<IOSurfaceRef> mSurface;
     gfx::IntRegion mInvalidRegion;
   };
--- a/gfx/layers/NativeLayerCA.mm
+++ b/gfx/layers/NativeLayerCA.mm
@@ -261,21 +261,19 @@ IntRegion NativeLayerCA::CurrentSurfaceI
 
   MOZ_RELEASE_ASSERT(
       mInProgressSurface,
       "Only call currentSurfaceInvalidRegion after a call to NextSurface and before the call "
       "to notifySurfaceIsReady.");
   return mInProgressSurface->mInvalidRegion;
 }
 
-void NativeLayerCA::InvalidateRegionThroughoutSwapchain(const IntRegion& aRegion) {
-  MutexAutoLock lock(mMutex);
-
+void NativeLayerCA::InvalidateRegionThroughoutSwapchain(const MutexAutoLock&,
+                                                        const IntRegion& aRegion) {
   IntRegion r = aRegion;
-  r.AndWith(IntRect(IntPoint(0, 0), mSize));
   if (mInProgressSurface) {
     mInProgressSurface->mInvalidRegion.OrWith(r);
   }
   if (mReadySurface) {
     mReadySurface->mInvalidRegion.OrWith(r);
   }
   for (auto& surf : mSurfaces) {
     surf.mInvalidRegion.OrWith(r);
@@ -333,23 +331,27 @@ CFTypeRefPtr<IOSurfaceRef> NativeLayerCA
   unusedSurfaces.clear();
 
   MOZ_RELEASE_ASSERT(surf);
   mInProgressSurface = std::move(surf);
   IOSurfaceIncrementUseCount(mInProgressSurface->mSurface.get());
   return mInProgressSurface->mSurface;
 }
 
-RefPtr<gfx::DrawTarget> NativeLayerCA::NextSurfaceAsDrawTarget(gfx::BackendType aBackendType) {
+RefPtr<gfx::DrawTarget> NativeLayerCA::NextSurfaceAsDrawTarget(const gfx::IntRegion& aUpdateRegion,
+                                                               gfx::BackendType aBackendType) {
   MutexAutoLock lock(mMutex);
   CFTypeRefPtr<IOSurfaceRef> surface = NextSurface(lock);
   if (!surface) {
     return nullptr;
   }
 
+  MOZ_RELEASE_ASSERT(IntRect({}, mSize).Contains(aUpdateRegion.GetBounds()));
+  InvalidateRegionThroughoutSwapchain(lock, aUpdateRegion);
+
   mInProgressLockedIOSurface = new MacIOSurface(std::move(surface));
   mInProgressLockedIOSurface->Lock(false);
   return mInProgressLockedIOSurface->GetAsDrawTargetLocked(aBackendType);
 }
 
 void NativeLayerCA::SetGLContext(gl::GLContext* aContext) {
   MutexAutoLock lock(mMutex);
 
@@ -362,23 +364,26 @@ void NativeLayerCA::SetGLContext(gl::GLC
   }
 }
 
 gl::GLContext* NativeLayerCA::GetGLContext() {
   MutexAutoLock lock(mMutex);
   return mGLContext;
 }
 
-Maybe<GLuint> NativeLayerCA::NextSurfaceAsFramebuffer(bool aNeedsDepth) {
+Maybe<GLuint> NativeLayerCA::NextSurfaceAsFramebuffer(const gfx::IntRegion& aUpdateRegion,
+                                                      bool aNeedsDepth) {
   MutexAutoLock lock(mMutex);
   CFTypeRefPtr<IOSurfaceRef> surface = NextSurface(lock);
   if (!surface) {
     return Nothing();
   }
 
+  MOZ_RELEASE_ASSERT(IntRect({}, mSize).Contains(aUpdateRegion.GetBounds()));
+  InvalidateRegionThroughoutSwapchain(lock, aUpdateRegion);
   return Some(GetOrCreateFramebufferForSurface(lock, std::move(surface), aNeedsDepth));
 }
 
 GLuint NativeLayerCA::GetOrCreateFramebufferForSurface(const MutexAutoLock&,
                                                        CFTypeRefPtr<IOSurfaceRef> aSurface,
                                                        bool aNeedsDepth) {
   auto fbCursor = mFramebuffers.find(aSurface);
   if (fbCursor != mFramebuffers.end()) {
--- a/gfx/layers/basic/BasicCompositor.cpp
+++ b/gfx/layers/basic/BasicCompositor.cpp
@@ -1029,19 +1029,18 @@ Maybe<gfx::IntRect> BasicCompositor::Beg
 
   if (mInvalidRegion.IsEmpty()) {
     return Nothing();
   }
 
   RefPtr<CompositingRenderTarget> target;
   aNativeLayer->SetSurfaceIsFlipped(false);
   IntRegion invalidRelativeToLayer = mInvalidRegion.MovedBy(-rect.TopLeft());
-  aNativeLayer->InvalidateRegionThroughoutSwapchain(invalidRelativeToLayer);
-  RefPtr<DrawTarget> dt =
-      aNativeLayer->NextSurfaceAsDrawTarget(BackendType::SKIA);
+  RefPtr<DrawTarget> dt = aNativeLayer->NextSurfaceAsDrawTarget(
+      invalidRelativeToLayer, BackendType::SKIA);
   if (!dt) {
     return Nothing();
   }
   invalidRelativeToLayer = aNativeLayer->CurrentSurfaceInvalidRegion();
   mInvalidRegion = invalidRelativeToLayer.MovedBy(rect.TopLeft());
   MOZ_RELEASE_ASSERT(!mInvalidRegion.IsEmpty());
   mCurrentNativeLayer = aNativeLayer;
   IntRegion clearRegion;
--- a/gfx/layers/composite/LayerManagerComposite.cpp
+++ b/gfx/layers/composite/LayerManagerComposite.cpp
@@ -842,18 +842,18 @@ void LayerManagerComposite::UpdateDebugO
     IntSize size = mTextRenderer->ComputeSurfaceSize(
         text, 600, TextRenderer::FontType::FixedWidth);
 
     if (!mGPUStatsLayer || mGPUStatsLayer->GetSize() != size) {
       mGPUStatsLayer = mNativeLayerRoot->CreateLayer(size, false);
     }
 
     mGPUStatsLayer->SetPosition(IntPoint(2, 5));
-    RefPtr<DrawTarget> dt =
-        mGPUStatsLayer->NextSurfaceAsDrawTarget(BackendType::SKIA);
+    RefPtr<DrawTarget> dt = mGPUStatsLayer->NextSurfaceAsDrawTarget(
+        IntRect({}, size), BackendType::SKIA);
     mTextRenderer->RenderTextToDrawTarget(dt, text, 600,
                                           TextRenderer::FontType::FixedWidth);
     mGPUStatsLayer->NotifySurfaceReady();
     mNativeLayerRoot->AppendLayer(mGPUStatsLayer);
 
     // The two warning layers are created on demand and their content is only
     // drawn once. After that, they only get moved (if the window size changes)
     // and conditionally shown.
@@ -861,17 +861,17 @@ void LayerManagerComposite::UpdateDebugO
     if (mUnusedApzTransformWarning) {
       // If we have an unused APZ transform on this composite, draw a 20x20 red
       // box in the top-right corner.
       if (!mUnusedTransformWarningLayer) {
         mUnusedTransformWarningLayer =
             mNativeLayerRoot->CreateLayer(IntSize(20, 20), true);
         RefPtr<DrawTarget> dt =
             mUnusedTransformWarningLayer->NextSurfaceAsDrawTarget(
-                BackendType::SKIA);
+                IntRect(0, 0, 20, 20), BackendType::SKIA);
         dt->FillRect(Rect(0, 0, 20, 20), ColorPattern(Color(1, 0, 0, 1)));
         mUnusedTransformWarningLayer->NotifySurfaceReady();
       }
       mUnusedTransformWarningLayer->SetPosition(
           IntPoint(mRenderBounds.XMost() - 20, mRenderBounds.Y()));
       mNativeLayerRoot->AppendLayer(mUnusedTransformWarningLayer);
 
       mUnusedApzTransformWarning = false;
@@ -882,17 +882,17 @@ void LayerManagerComposite::UpdateDebugO
       // If we have a disabled APZ on this composite, draw a 20x20 yellow box
       // in the top-right corner, to the left of the unused-apz-transform
       // warning box.
       if (!mDisabledApzWarningLayer) {
         mDisabledApzWarningLayer =
             mNativeLayerRoot->CreateLayer(IntSize(20, 20), true);
         RefPtr<DrawTarget> dt =
             mDisabledApzWarningLayer->NextSurfaceAsDrawTarget(
-                BackendType::SKIA);
+                IntRect(0, 0, 20, 20), BackendType::SKIA);
         dt->FillRect(Rect(0, 0, 20, 20), ColorPattern(Color(1, 1, 0, 1)));
         mDisabledApzWarningLayer->NotifySurfaceReady();
       }
       mDisabledApzWarningLayer->SetPosition(
           IntPoint(mRenderBounds.XMost() - 40, mRenderBounds.Y()));
       mNativeLayerRoot->AppendLayer(mDisabledApzWarningLayer);
 
       mDisabledApzWarning = false;
--- a/gfx/layers/opengl/CompositorOGL.cpp
+++ b/gfx/layers/opengl/CompositorOGL.cpp
@@ -764,18 +764,18 @@ CompositorOGL::RenderTargetForNativeLaye
   }
 
   aNativeLayer->SetSurfaceIsFlipped(true);
   aNativeLayer->SetGLContext(mGLContext);
 
   IntRect layerRect = aNativeLayer->GetRect();
   IntRegion invalidRelativeToLayer =
       aInvalidRegion.MovedBy(-layerRect.TopLeft());
-  aNativeLayer->InvalidateRegionThroughoutSwapchain(invalidRelativeToLayer);
-  Maybe<GLuint> fbo = aNativeLayer->NextSurfaceAsFramebuffer(false);
+  Maybe<GLuint> fbo =
+      aNativeLayer->NextSurfaceAsFramebuffer(invalidRelativeToLayer, false);
   if (!fbo) {
     return nullptr;
   }
 
   invalidRelativeToLayer = aNativeLayer->CurrentSurfaceInvalidRegion();
   aInvalidRegion = invalidRelativeToLayer.MovedBy(layerRect.TopLeft());
 
   RefPtr<CompositingRenderTargetOGL> rt =
--- a/gfx/webrender_bindings/RenderCompositorOGL.cpp
+++ b/gfx/webrender_bindings/RenderCompositorOGL.cpp
@@ -63,34 +63,35 @@ RenderCompositorOGL::~RenderCompositorOG
 }
 
 bool RenderCompositorOGL::BeginFrame() {
   if (!mGL->MakeCurrent()) {
     gfxCriticalNote << "Failed to make render context current, can't draw.";
     return false;
   }
 
+  gfx::IntSize bufferSize = GetBufferSize().ToUnknownSize();
   if (mNativeLayerRoot && !ShouldUseNativeCompositor()) {
-    gfx::IntSize bufferSize = GetBufferSize().ToUnknownSize();
     if (mNativeLayerForEntireWindow &&
         mNativeLayerForEntireWindow->GetSize() != bufferSize) {
       mNativeLayerRoot->RemoveLayer(mNativeLayerForEntireWindow);
       mNativeLayerForEntireWindow = nullptr;
     }
     if (!mNativeLayerForEntireWindow) {
       mNativeLayerForEntireWindow =
           mNativeLayerRoot->CreateLayer(bufferSize, false);
       mNativeLayerForEntireWindow->SetSurfaceIsFlipped(true);
       mNativeLayerForEntireWindow->SetGLContext(mGL);
       mNativeLayerRoot->AppendLayer(mNativeLayerForEntireWindow);
     }
   }
   if (mNativeLayerForEntireWindow) {
+    gfx::IntRect bounds({}, bufferSize);
     Maybe<GLuint> fbo =
-        mNativeLayerForEntireWindow->NextSurfaceAsFramebuffer(true);
+        mNativeLayerForEntireWindow->NextSurfaceAsFramebuffer(bounds, true);
     if (!fbo) {
       return false;
     }
     mGL->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, *fbo);
   } else {
     mGL->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mGL->GetDefaultFramebuffer());
   }
 
@@ -183,17 +184,17 @@ void RenderCompositorOGL::Bind(wr::Nativ
   gfx::IntRect layerRect = layer->GetRect();
   gfx::IntRect dirtyRect(aDirtyRect.origin.x, aDirtyRect.origin.y,
                          aDirtyRect.size.width, aDirtyRect.size.height);
   MOZ_RELEASE_ASSERT(
       dirtyRect.IsEqualInterior(layerRect - layerRect.TopLeft()),
       "We currently do not support partial updates (max_update_rects is set to "
       "0), so we expect the dirty rect to always cover the entire layer.");
 
-  Maybe<GLuint> fbo = layer->NextSurfaceAsFramebuffer(true);
+  Maybe<GLuint> fbo = layer->NextSurfaceAsFramebuffer(dirtyRect, true);
   MOZ_RELEASE_ASSERT(fbo);  // TODO: make fallible
   mCurrentlyBoundNativeLayer = layer;
 
   *aFboId = *fbo;
   *aOffset = wr::DeviceIntPoint{0, 0};
 
   mDrawnPixelCount += layerRect.Area();
 }
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -1503,18 +1503,18 @@ void nsChildView::EnsureContentLayerForM
     mContentLayer = contentLayer->AsNativeLayerCA();
     mContentLayerInvalidRegion = GetBounds();
   }
 }
 
 void nsChildView::PaintWindowInContentLayer() {
   EnsureContentLayerForMainThreadPainting();
   mContentLayer->SetSurfaceIsFlipped(false);
-  mContentLayer->InvalidateRegionThroughoutSwapchain(mContentLayerInvalidRegion.ToUnknownRegion());
-  RefPtr<DrawTarget> dt = mContentLayer->NextSurfaceAsDrawTarget(gfx::BackendType::SKIA);
+  RefPtr<DrawTarget> dt = mContentLayer->NextSurfaceAsDrawTarget(
+      mContentLayerInvalidRegion.ToUnknownRegion(), gfx::BackendType::SKIA);
   if (!dt) {
     return;
   }
 
   PaintWindowInDrawTarget(
       dt, LayoutDeviceIntRegion::FromUnknownRegion(mContentLayer->CurrentSurfaceInvalidRegion()),
       dt->GetSize());
   mContentLayer->NotifySurfaceReady();