Commit 90a8a6ad authored by Lee Salzman's avatar Lee Salzman
Browse files

Bug 1789849 - Avoid regenerating clip mask unless necessary. r=aosmond

Sometimes the clip state is thrashed when we need to temporarily override
clipping to disable it. However, in this case, the clip mask itself remains
unchanged. The current invalidation scheme doesn't discern between generation
of the clip mask itself and setting the clip state for the shader, leading to
unnecessary regeneration of the clip mask.

This code just tries to discern when this is happening so we can refresh the
clip state without having to regenerate the clip mask unless truly necessary.

Differential Revision: https://phabricator.services.mozilla.com/D157048
parent 095bc04f
Loading
Loading
Loading
Loading
+14 −10
Original line number Diff line number Diff line
@@ -532,7 +532,7 @@ bool DrawTargetWebgl::SharedContext::SetNoClipMask() {
// render to the Skia target temporarily, transparent outside the clip region,
// opaque inside, and upload this to a texture that can be used by the shaders.
bool DrawTargetWebgl::GenerateComplexClipMask() {
  if (!mClipDirty) {
  if (!mClipChanged) {
    // If the clip mask was already generated, use the cached mask and bounds.
    mSharedContext->SetClipMask(mClipMask);
    mSharedContext->SetClipRect(mClipBounds);
@@ -596,7 +596,6 @@ bool DrawTargetWebgl::GenerateComplexClipMask() {
  mSharedContext->SetClipRect(mClipBounds);
  // The Skia target contents was clobbered and is now invalid.
  mSkiaValid = false;
  mClipDirty = false;
  return !!data;
}

@@ -617,7 +616,6 @@ bool DrawTargetWebgl::SetSimpleClipRect() {
  }
  mSharedContext->SetClipRect(*clip);
  mSharedContext->SetNoClipMask();
  mClipDirty = false;
  return true;
}

@@ -629,13 +627,15 @@ bool DrawTargetWebgl::PrepareContext(bool aClipped) {
    mSharedContext->SetClipRect(IntRect(IntPoint(), mSize));
    mSharedContext->SetNoClipMask();
    // Ensure the clip gets reset if clipping is later requested for the target.
    mClipDirty = true;
  } else if (mClipDirty || !mSharedContext->IsCurrentTarget(this)) {
    mRefreshClipState = true;
  } else if (mRefreshClipState || !mSharedContext->IsCurrentTarget(this)) {
    // Try to use a simple clip rect if possible. Otherwise, fall back to
    // generating a clip mask texture that can represent complex clip regions.
    if (!SetSimpleClipRect() && !GenerateComplexClipMask()) {
      return false;
    }
    mClipChanged = false;
    mRefreshClipState = false;
  }
  return mSharedContext->SetTarget(this);
}
@@ -786,7 +786,7 @@ inline DrawTargetWebgl::AutoRestoreContext::~AutoRestoreContext() {
  if (mLastClipMask) {
    mTarget->mSharedContext->SetClipMask(mLastClipMask);
  }
  mTarget->mClipDirty = true;
  mTarget->mRefreshClipState = true;
}

// Utility method to install the target before copying a snapshot.
@@ -1217,23 +1217,27 @@ void DrawTargetWebgl::CopySurface(SourceSurface* aSurface,
}

void DrawTargetWebgl::PushClip(const Path* aPath) {
  mClipDirty = true;
  mClipChanged = true;
  mRefreshClipState = true;
  mSkia->PushClip(aPath);
}

void DrawTargetWebgl::PushClipRect(const Rect& aRect) {
  mClipDirty = true;
  mClipChanged = true;
  mRefreshClipState = true;
  mSkia->PushClipRect(aRect);
}

void DrawTargetWebgl::PushDeviceSpaceClipRects(const IntRect* aRects,
                                               uint32_t aCount) {
  mClipDirty = true;
  mClipChanged = true;
  mRefreshClipState = true;
  mSkia->PushDeviceSpaceClipRects(aRects, aCount);
}

void DrawTargetWebgl::PopClip() {
  mClipDirty = true;
  mClipChanged = true;
  mRefreshClipState = true;
  mSkia->PopClip();
}

+5 −1
Original line number Diff line number Diff line
@@ -82,7 +82,11 @@ class DrawTargetWebgl : public DrawTarget, public SupportsWeakPtr {
  // Whether or not the WebGL context has valid contents and is being drawn to
  bool mWebglValid = true;
  // Whether or not the clip state has changed since last used by SharedContext.
  bool mClipDirty = true;
  bool mClipChanged = true;
  // Whether or not the clip state needs to be refreshed. Sometimes the clip
  // state may be overwritten and require a refresh later, even though it has
  // not changed.
  bool mRefreshClipState = true;
  // The framebuffer has been modified and should be copied to the swap chain.
  bool mNeedsPresent = true;
  // The number of layers currently pushed.