Пример #1
0
already_AddRefed<DrawTarget>
nsShmImage::CreateDrawTarget(const mozilla::LayoutDeviceIntRegion& aRegion)
{
  // Wait for any in-flight requests to complete.
  // Typically X clients would wait for a XShmCompletionEvent to be received,
  // but this works as it's sent immediately after the request is processed.
  xcb_generic_error_t* error;
  if (mLastRequest.sequence != XCB_NONE &&
      (error = xcb_request_check(mConnection, mLastRequest)))
  {
    gShmAvailable = false;
    free(error);
    return nullptr;
  }

  // Due to bug 1205045, we must avoid making GTK calls off the main thread to query window size.
  // Instead we just track the largest offset within the image we are drawing to and grow the image
  // to accomodate it. Since usually the entire window is invalidated on the first paint to it,
  // this should grow the image to the necessary size quickly without many intermediate reallocations.
  IntRect bounds = aRegion.GetBounds().ToUnknownRect();
  IntSize size(bounds.XMost(), bounds.YMost());
  if (size.width > mSize.width || size.height > mSize.height) {
    DestroyImage();
    if (!CreateImage(size)) {
      return nullptr;
    }
  }

  return gfxPlatform::GetPlatform()->CreateDrawTargetForData(
    reinterpret_cast<unsigned char*>(mShmAddr)
      + BytesPerPixel(mFormat) * (bounds.y * mSize.width + bounds.x),
    bounds.Size(),
    BytesPerPixel(mFormat) * mSize.width,
    mFormat);
}
Пример #2
0
gfx::DrawTarget*
TiledTextureImage::BeginUpdate(nsIntRegion& aRegion)
{
    NS_ASSERTION(!mInUpdate, "nested update");
    mInUpdate = true;

    // Note, we don't call GetUpdateRegion here as if the updated region is
    // fully contained in a single tile, we get to avoid iterating through
    // the tiles again (and a little copying).
    if (mTextureState != Valid)
    {
        // if the texture hasn't been initialized yet, or something important
        // changed, we need to recreate our backing surface and force the
        // client to paint everything
        aRegion = IntRect(IntPoint(0, 0), mSize);
    }

    IntRect bounds = aRegion.GetBounds();

    for (unsigned i = 0; i < mImages.Length(); i++) {
        int xPos = (i % mColumns) * mTileSize;
        int yPos = (i / mColumns) * mTileSize;
        nsIntRegion imageRegion =
          nsIntRegion(IntRect(IntPoint(xPos,yPos),
                                mImages[i]->GetSize()));

        // a single Image can handle this update request
        if (imageRegion.Contains(aRegion)) {
            // adjust for tile offset
            aRegion.MoveBy(-xPos, -yPos);
            // forward the actual call
            RefPtr<gfx::DrawTarget> drawTarget = mImages[i]->BeginUpdate(aRegion);
            // caller expects container space
            aRegion.MoveBy(xPos, yPos);
            // we don't have a temp surface
            mUpdateDrawTarget = nullptr;
            // remember which image to EndUpdate
            mCurrentImage = i;
            return drawTarget.get();
        }
    }

    // Get the real updated region, taking into account the capabilities of
    // each TextureImage tile
    GetUpdateRegion(aRegion);
    mUpdateRegion = aRegion;
    bounds = aRegion.GetBounds();

    // update covers multiple Images - create a temp surface to paint in
    gfx::SurfaceFormat format =
        (GetContentType() == gfxContentType::COLOR) ?
        gfx::SurfaceFormat::B8G8R8X8: gfx::SurfaceFormat::B8G8R8A8;
    mUpdateDrawTarget = gfx::Factory::CreateDrawTarget(gfx::BackendType::CAIRO,
                                                       bounds.Size(),
                                                       format);

    return mUpdateDrawTarget;;
}
Пример #3
0
IntSize
DeprecatedTextureHostD3D9::GetSize() const
{
  if (mIterating) {
    IntRect rect = GetTileRect(mCurrentTile);
    return rect.Size();
  }
  return TextureSourceD3D9::GetSize();
}
Пример #4
0
TemporaryRef<CompositingRenderTarget>
BasicCompositor::CreateRenderTarget(const IntRect& aRect, SurfaceInitMode aInit)
{
  RefPtr<DrawTarget> target = mDrawTarget->CreateSimilarDrawTarget(aRect.Size(), SurfaceFormat::B8G8R8A8);

  RefPtr<BasicCompositingRenderTarget> rt = new BasicCompositingRenderTarget(target, aRect);

  return rt.forget();
}
Пример #5
0
/* static */
already_AddRefed<VideoData>
VideoData::Create(const VideoInfo& aInfo,
                  ImageContainer* aContainer,
                  int64_t aOffset,
                  int64_t aTime,
                  int64_t aDuration,
                  mozilla::layers::TextureClient* aBuffer,
                  bool aKeyframe,
                  int64_t aTimecode,
                  const IntRect& aPicture)
{
  if (!aContainer) {
    // Create a dummy VideoData with no image. This gives us something to
    // send to media streams if necessary.
    RefPtr<VideoData> v(new VideoData(aOffset,
                                        aTime,
                                        aDuration,
                                        aKeyframe,
                                        aTimecode,
                                        aInfo.mDisplay,
                                        0));
    return v.forget();
  }

  // The following situations could be triggered by invalid input
  if (aPicture.width <= 0 || aPicture.height <= 0) {
    NS_WARNING("Empty picture rect");
    return nullptr;
  }

  // Ensure the picture size specified in the headers can be extracted out of
  // the frame we've been supplied without indexing out of bounds.
  CheckedUint32 xLimit = aPicture.x + CheckedUint32(aPicture.width);
  CheckedUint32 yLimit = aPicture.y + CheckedUint32(aPicture.height);
  if (!xLimit.isValid() || !yLimit.isValid())
  {
    // The specified picture dimensions can't be contained inside the video
    // frame, we'll stomp memory if we try to copy it. Fail.
    NS_WARNING("Overflowing picture rect");
    return nullptr;
  }

  RefPtr<VideoData> v(new VideoData(aOffset,
                                      aTime,
                                      aDuration,
                                      aKeyframe,
                                      aTimecode,
                                      aInfo.mDisplay,
                                      0));

  RefPtr<layers::GrallocImage> image = new layers::GrallocImage();
  image->AdoptData(aBuffer, aPicture.Size());
  v->mImage = image;

  return v.forget();
}
Пример #6
0
void
ClientLayerManager::MakeSnapshotIfRequired()
{
  if (!mShadowTarget) {
    return;
  }
  if (mWidget) {
    if (CompositorBridgeChild* remoteRenderer = GetRemoteRenderer()) {
      // The compositor doesn't draw to a different sized surface
      // when there's a rotation. Instead we rotate the result
      // when drawing into dt
      LayoutDeviceIntRect outerBounds;
      mWidget->GetBounds(outerBounds);

      IntRect bounds = ToOutsideIntRect(mShadowTarget->GetClipExtents());
      if (mTargetRotation) {
        bounds =
          RotateRect(bounds, outerBounds.ToUnknownRect(), mTargetRotation);
      }

      SurfaceDescriptor inSnapshot;
      if (!bounds.IsEmpty() &&
          mForwarder->AllocSurfaceDescriptor(bounds.Size(),
                                             gfxContentType::COLOR_ALPHA,
                                             &inSnapshot)) {

        // Make a copy of |inSnapshot| because the call to send it over IPC
        // will call forget() on the Shmem inside, and zero it out.
        SurfaceDescriptor outSnapshot = inSnapshot;

        if (remoteRenderer->SendMakeSnapshot(inSnapshot, bounds)) {
          RefPtr<DataSourceSurface> surf = GetSurfaceForDescriptor(outSnapshot);
          DrawTarget* dt = mShadowTarget->GetDrawTarget();

          Rect dstRect(bounds.x, bounds.y, bounds.width, bounds.height);
          Rect srcRect(0, 0, bounds.width, bounds.height);

          gfx::Matrix rotate =
            ComputeTransformForUnRotation(outerBounds.ToUnknownRect(),
                                          mTargetRotation);

          gfx::Matrix oldMatrix = dt->GetTransform();
          dt->SetTransform(rotate * oldMatrix);
          dt->DrawSurface(surf, dstRect, srcRect,
                          DrawSurfaceOptions(),
                          DrawOptions(1.0f, CompositionOp::OP_OVER));
          dt->SetTransform(oldMatrix);
        }
        mForwarder->DestroySurfaceDescriptor(&outSnapshot);
      }
    }
  }
  mShadowTarget = nullptr;
}
Пример #7
0
void
DrawTargetTiled::CopySurface(SourceSurface *aSurface,
                             const IntRect &aSourceRect,
                             const IntPoint &aDestination)
{
  for (size_t i = 0; i < mTiles.size(); i++) {
    IntPoint tileOrigin = mTiles[i].mTileOrigin;
    IntSize tileSize = mTiles[i].mDrawTarget->GetSize();
    if (!IntRect(aDestination, aSourceRect.Size()).Intersects(IntRect(tileOrigin, tileSize))) {
      continue;
    }
    // CopySurface ignores the transform, account for that here.
    mTiles[i].mDrawTarget->CopySurface(aSurface, aSourceRect, aDestination - tileOrigin);
  }
}
Пример #8
0
/**
 * aSrcRect: Rect relative to the aSrc surface
 * aDestPoint: Point inside aDest surface
 */
void
CopyRect(DataSourceSurface* aSrc, DataSourceSurface* aDest,
         IntRect aSrcRect, IntPoint aDestPoint)
{
  if (aSrcRect.Overflows() ||
      IntRect(aDestPoint, aSrcRect.Size()).Overflows()) {
    MOZ_CRASH("we should never be getting invalid rects at this point");
  }

  MOZ_RELEASE_ASSERT(aSrc->GetFormat() == aDest->GetFormat(),
                     "different surface formats");
  MOZ_RELEASE_ASSERT(IntRect(IntPoint(), aSrc->GetSize()).Contains(aSrcRect),
                     "source rect too big for source surface");
  MOZ_RELEASE_ASSERT(IntRect(IntPoint(), aDest->GetSize()).Contains(IntRect(aDestPoint, aSrcRect.Size())),
                     "dest surface too small");

  if (aSrcRect.IsEmpty()) {
    return;
  }

  DataSourceSurface::ScopedMap srcMap(aSrc, DataSourceSurface::READ);
  DataSourceSurface::ScopedMap destMap(aDest, DataSourceSurface::WRITE);
  if (MOZ2D_WARN_IF(!srcMap.IsMapped() || !destMap.IsMapped())) {
    return;
  }

  uint8_t* sourceData = DataAtOffset(aSrc, srcMap.GetMappedSurface(), aSrcRect.TopLeft());
  uint32_t sourceStride = srcMap.GetStride();
  uint8_t* destData = DataAtOffset(aDest, destMap.GetMappedSurface(), aDestPoint);
  uint32_t destStride = destMap.GetStride();

  if (BytesPerPixel(aSrc->GetFormat()) == 4) {
    for (int32_t y = 0; y < aSrcRect.height; y++) {
      PodCopy((int32_t*)destData, (int32_t*)sourceData, aSrcRect.width);
      sourceData += sourceStride;
      destData += destStride;
    }
  } else if (BytesPerPixel(aSrc->GetFormat()) == 1) {
    for (int32_t y = 0; y < aSrcRect.height; y++) {
      PodCopy(destData, sourceData, aSrcRect.width);
      sourceData += sourceStride;
      destData += destStride;
    }
  }
}
Пример #9
0
already_AddRefed<CompositingRenderTarget>
BasicCompositor::CreateRenderTarget(const IntRect& aRect, SurfaceInitMode aInit)
{
  MOZ_ASSERT(aRect.width != 0 && aRect.height != 0, "Trying to create a render target of invalid size");

  if (aRect.width * aRect.height == 0) {
    return nullptr;
  }

  RefPtr<DrawTarget> target = mDrawTarget->CreateSimilarDrawTarget(aRect.Size(), SurfaceFormat::B8G8R8A8);

  if (!target) {
    return nullptr;
  }

  RefPtr<BasicCompositingRenderTarget> rt = new BasicCompositingRenderTarget(target, aRect);

  return rt.forget();
}
Пример #10
0
already_AddRefed<DrawTarget>
nsSVGClipPathFrame::CreateClipMask(gfxContext& aReferenceContext,
                                   IntPoint& aOffset)
{
    gfxContextMatrixAutoSaveRestore autoRestoreMatrix(&aReferenceContext);

    aReferenceContext.SetMatrix(gfxMatrix());
    gfxRect rect = aReferenceContext.GetClipExtents();
    IntRect bounds = RoundedOut(ToRect(rect));
    if (bounds.IsEmpty()) {
        // We don't need to create a mask surface, all drawing is clipped anyway.
        return nullptr;
    }

    DrawTarget* referenceDT = aReferenceContext.GetDrawTarget();
    RefPtr<DrawTarget> maskDT =
        referenceDT->CreateSimilarDrawTarget(bounds.Size(), SurfaceFormat::A8);

    aOffset = bounds.TopLeft();

    return maskDT.forget();
}
Пример #11
0
/* static */
bool VideoData::SetVideoDataToImage(PlanarYCbCrImage* aVideoImage,
                                    const VideoInfo& aInfo,
                                    const YCbCrBuffer &aBuffer,
                                    const IntRect& aPicture,
                                    bool aCopyData)
{
  if (!aVideoImage) {
    return false;
  }
  const YCbCrBuffer::Plane &Y = aBuffer.mPlanes[0];
  const YCbCrBuffer::Plane &Cb = aBuffer.mPlanes[1];
  const YCbCrBuffer::Plane &Cr = aBuffer.mPlanes[2];

  PlanarYCbCrData data;
  data.mYChannel = Y.mData + Y.mOffset;
  data.mYSize = IntSize(Y.mWidth, Y.mHeight);
  data.mYStride = Y.mStride;
  data.mYSkip = Y.mSkip;
  data.mCbChannel = Cb.mData + Cb.mOffset;
  data.mCrChannel = Cr.mData + Cr.mOffset;
  data.mCbCrSize = IntSize(Cb.mWidth, Cb.mHeight);
  data.mCbCrStride = Cb.mStride;
  data.mCbSkip = Cb.mSkip;
  data.mCrSkip = Cr.mSkip;
  data.mPicX = aPicture.x;
  data.mPicY = aPicture.y;
  data.mPicSize = aPicture.Size();
  data.mStereoMode = aInfo.mStereoMode;

  aVideoImage->SetDelayedConversion(true);
  if (aCopyData) {
    return aVideoImage->SetData(data);
  } else {
    return aVideoImage->SetDataNoCopy(data);
  }
}
Пример #12
0
/* static */ void
gfxAlphaBoxBlur::BlurRectangle(gfxContext* aDestinationCtx,
                               const gfxRect& aRect,
                               RectCornerRadii* aCornerRadii,
                               const gfxPoint& aBlurStdDev,
                               const gfxRGBA& aShadowColor,
                               const gfxRect& aDirtyRect,
                               const gfxRect& aSkipRect)
{
  DrawTarget& destDrawTarget = *aDestinationCtx->GetDrawTarget();
  IntSize blurRadius = CalculateBlurRadius(aBlurStdDev);

  IntRect rect = RoundedToInt(ToRect(aRect));
  IntMargin extendDestBy;
  IntMargin slice;

  RefPtr<SourceSurface> boxShadow = GetBlur(destDrawTarget,
                                            rect.Size(), blurRadius,
                                            aCornerRadii, aShadowColor,
                                            extendDestBy, slice);
  if (!boxShadow) {
    return;
  }

  destDrawTarget.PushClipRect(ToRect(aDirtyRect));

  // Copy the right parts from boxShadow into destDrawTarget. The middle parts
  // will be stretched, border-image style.

  Rect srcOuter(Point(), Size(boxShadow->GetSize()));
  Rect srcInner = srcOuter;
  srcInner.Deflate(Margin(slice));

  rect.Inflate(extendDestBy);
  Rect dstOuter(rect);
  Rect dstInner(rect);
  dstInner.Deflate(Margin(slice));

  Rect skipRect = ToRect(aSkipRect);

  if (srcInner.IsEqualInterior(srcOuter)) {
    MOZ_ASSERT(dstInner.IsEqualInterior(dstOuter));
    // The target rect is smaller than the minimal size so just draw the surface
    destDrawTarget.DrawSurface(boxShadow, dstInner, srcInner);
  } else {
    DrawBoxShadows(destDrawTarget, boxShadow, dstOuter, dstInner,
                   srcOuter, srcInner, skipRect);

    // Middle part
    RepeatOrStretchSurface(destDrawTarget, boxShadow,
                           RectWithEdgesTRBL(dstInner.Y(), dstInner.XMost(),
                                             dstInner.YMost(), dstInner.X()),
                           RectWithEdgesTRBL(srcInner.Y(), srcInner.XMost(),
                                             srcInner.YMost(), srcInner.X()),
                           skipRect);
  }

  // A note about anti-aliasing and seems between adjacent parts:
  // We don't explicitly disable anti-aliasing in the DrawSurface calls above,
  // so if there's a transform on destDrawTarget that is not pixel-aligned,
  // there will be seams between adjacent parts of the box-shadow. It's hard to
  // avoid those without the use of an intermediate surface.
  // You might think that we could avoid those by just turning of AA, but there
  // is a problem with that: Box-shadow rendering needs to clip out the
  // element's border box, and we'd like that clip to have anti-aliasing -
  // especially if the element has rounded corners! So we can't do that unless
  // we have a way to say "Please anti-alias the clip, but don't antialias the
  // destination rect of the DrawSurface call".
  // On OS X there is an additional problem with turning off AA: CoreGraphics
  // will not just fill the pixels that have their pixel center inside the
  // filled shape. Instead, it will fill all the pixels which are partially
  // covered by the shape. So for pixels on the edge between two adjacent parts,
  // all those pixels will be painted to by both parts, which looks very bad.

  destDrawTarget.PopClip();
}
Пример #13
0
void
nsSVGIntegrationUtils::PaintFramesWithEffects(gfxContext& aContext,
                                              nsIFrame* aFrame,
                                              const nsRect& aDirtyRect,
                                              const nsRect& aBorderArea,
                                              nsDisplayListBuilder* aBuilder,
                                              LayerManager *aLayerManager)
{
#ifdef DEBUG
  NS_ASSERTION(!(aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT) ||
               (NS_SVGDisplayListPaintingEnabled() &&
                !(aFrame->GetStateBits() & NS_FRAME_IS_NONDISPLAY)),
               "Should not use nsSVGIntegrationUtils on this SVG frame");
#endif

  /* SVG defines the following rendering model:
   *
   *  1. Render geometry
   *  2. Apply filter
   *  3. Apply clipping, masking, group opacity
   *
   * We follow this, but perform a couple of optimizations:
   *
   * + Use cairo's clipPath when representable natively (single object
   *   clip region).
   *
   * + Merge opacity and masking if both used together.
   */

  const nsIContent* content = aFrame->GetContent();
  bool hasSVGLayout = (aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT);
  if (hasSVGLayout) {
    nsISVGChildFrame *svgChildFrame = do_QueryFrame(aFrame);
    if (!svgChildFrame || !aFrame->GetContent()->IsSVGElement()) {
      NS_ASSERTION(false, "why?");
      return;
    }
    if (!static_cast<const nsSVGElement*>(content)->HasValidDimensions()) {
      return; // The SVG spec says not to draw _anything_
    }
  }

  float opacity = aFrame->StyleDisplay()->mOpacity;
  if (opacity == 0.0f) {
    return;
  }
  if (opacity != 1.0f &&
      hasSVGLayout && nsSVGUtils::CanOptimizeOpacity(aFrame)) {
    opacity = 1.0f;
  }

  /* Properties are added lazily and may have been removed by a restyle,
     so make sure all applicable ones are set again. */
  nsIFrame* firstFrame =
    nsLayoutUtils::FirstContinuationOrIBSplitSibling(aFrame);
  nsSVGEffects::EffectProperties effectProperties =
    nsSVGEffects::GetEffectProperties(firstFrame);

  bool isOK = effectProperties.HasNoFilterOrHasValidFilter();
  nsSVGClipPathFrame *clipPathFrame = effectProperties.GetClipPathFrame(&isOK);

  bool isTrivialClip = clipPathFrame ? clipPathFrame->IsTrivial() : true;

  DrawTarget* drawTarget = aContext.GetDrawTarget();
  gfxContextMatrixAutoSaveRestore matrixAutoSaveRestore(&aContext);

  nsPoint firstFrameOffset = GetOffsetToBoundingBox(firstFrame);
  nsPoint offsetToBoundingBox = aBuilder->ToReferenceFrame(firstFrame) - firstFrameOffset;
  if (!firstFrame->IsFrameOfType(nsIFrame::eSVG)) {
    /* Snap the offset if the reference frame is not a SVG frame,
     * since other frames will be snapped to pixel when rendering. */
    offsetToBoundingBox = nsPoint(
      aFrame->PresContext()->RoundAppUnitsToNearestDevPixels(offsetToBoundingBox.x),
      aFrame->PresContext()->RoundAppUnitsToNearestDevPixels(offsetToBoundingBox.y));
  }

  // After applying only "offsetToBoundingBox", aCtx would have its origin at
  // the top left corner of aFrame's bounding box (over all continuations).
  // However, SVG painting needs the origin to be located at the origin of the
  // SVG frame's "user space", i.e. the space in which, for example, the
  // frame's BBox lives.
  // SVG geometry frames and foreignObject frames apply their own offsets, so
  // their position is relative to their user space. So for these frame types,
  // if we want aCtx to be in user space, we first need to subtract the
  // frame's position so that SVG painting can later add it again and the
  // frame is painted in the right place.

  gfxPoint toUserSpaceGfx = nsSVGUtils::FrameSpaceInCSSPxToUserSpaceOffset(aFrame);
  nsPoint toUserSpace(nsPresContext::CSSPixelsToAppUnits(float(toUserSpaceGfx.x)),
                      nsPresContext::CSSPixelsToAppUnits(float(toUserSpaceGfx.y)));
  nsPoint offsetToUserSpace = offsetToBoundingBox - toUserSpace;

  NS_ASSERTION(hasSVGLayout || offsetToBoundingBox == offsetToUserSpace,
               "For non-SVG frames there shouldn't be any additional offset");

  gfxPoint devPixelOffsetToUserSpace =
    nsLayoutUtils::PointToGfxPoint(offsetToUserSpace,
                                   aFrame->PresContext()->AppUnitsPerDevPixel());
  aContext.SetMatrix(aContext.CurrentMatrix().Translate(devPixelOffsetToUserSpace));

  gfxMatrix cssPxToDevPxMatrix = GetCSSPxToDevPxMatrix(aFrame);

  const nsStyleSVGReset *svgReset = firstFrame->StyleSVGReset();
  // Keep moving forward even if svgMaskFrame is nullptr or isOK is false.
  // This source is not a svg mask, but it still can be a correct mask image.
  nsSVGMaskFrame *svgMaskFrame = effectProperties.GetMaskFrame(&isOK);

  bool complexEffects = false;
  bool hasValidLayers = svgReset->mMask.HasLayerWithImage();

  // These are used if we require a temporary surface for a custom blend mode.
  RefPtr<gfxContext> target = &aContext;
  IntPoint targetOffset;

  /* Check if we need to do additional operations on this child's
   * rendering, which necessitates rendering into another surface. */
  if (opacity != 1.0f ||  (clipPathFrame && !isTrivialClip)
      || aFrame->StyleDisplay()->mMixBlendMode != NS_STYLE_BLEND_NORMAL
      || svgMaskFrame || hasValidLayers) {
    complexEffects = true;

    aContext.Save();
    nsRect clipRect =
      aFrame->GetVisualOverflowRectRelativeToSelf() + toUserSpace;
    aContext.Clip(NSRectToSnappedRect(clipRect,
                                  aFrame->PresContext()->AppUnitsPerDevPixel(),
                                  *drawTarget));

    Matrix maskTransform;
    RefPtr<SourceSurface> maskSurface;
    if (svgMaskFrame) {
      maskSurface = svgMaskFrame->GetMaskForMaskedFrame(&aContext,
                                                     aFrame,
                                                     cssPxToDevPxMatrix,
                                                     opacity,
                                                     &maskTransform);
    } else if (hasValidLayers) {
      gfxRect clipRect = aContext.GetClipExtents();
      {
        gfxContextMatrixAutoSaveRestore matRestore(&aContext);

        aContext.SetMatrix(gfxMatrix());
        clipRect = aContext.GetClipExtents();
      }
      IntRect drawRect = RoundedOut(ToRect(clipRect));
      RefPtr<DrawTarget> targetDT = aContext.GetDrawTarget()->CreateSimilarDrawTarget(drawRect.Size(), SurfaceFormat::A8);
      if (!targetDT) {
        aContext.Restore();
        return;
      }

      RefPtr<gfxContext> target = new gfxContext(targetDT);
      target->SetMatrix(matrixAutoSaveRestore.Matrix() * gfxMatrix::Translation(-drawRect.TopLeft()));

      // Generate mask surface.
      uint32_t flags = aBuilder->GetBackgroundPaintFlags() |
                       nsCSSRendering::PAINTBG_MASK_IMAGE;
      nsRenderingContext rc(target);
      nsCSSRendering::PaintBackgroundWithSC(aFrame->PresContext(),
                                            rc,
                                            aFrame,
                                            aDirtyRect,
                                            aBorderArea,
                                            firstFrame->StyleContext(),
                                            *aFrame->StyleBorder(),
                                            flags,
                                            nullptr,
                                            -1);
      maskSurface = targetDT->Snapshot();

      // Compute mask transform.
      Matrix mat = ToMatrix(aContext.CurrentMatrix());
      mat.Invert();
      maskTransform = Matrix::Translation(drawRect.x, drawRect.y) * mat;
    }

    if ((svgMaskFrame || hasValidLayers) && !maskSurface) {
      // Entire surface is clipped out.
      aContext.Restore();
      return;
    }

    if (aFrame->StyleDisplay()->mMixBlendMode != NS_STYLE_BLEND_NORMAL) {
      // Create a temporary context to draw to so we can blend it back with
      // another operator.
      gfxRect clipRect;
      {
        gfxContextMatrixAutoSaveRestore matRestore(&aContext);

        aContext.SetMatrix(gfxMatrix());
        clipRect = aContext.GetClipExtents();
      }

      IntRect drawRect = RoundedOut(ToRect(clipRect));

      RefPtr<DrawTarget> targetDT = aContext.GetDrawTarget()->CreateSimilarDrawTarget(drawRect.Size(), SurfaceFormat::B8G8R8A8);
      if (!targetDT) {
        aContext.Restore();
        return;
      }
      target = new gfxContext(targetDT);
      target->SetMatrix(aContext.CurrentMatrix() * gfxMatrix::Translation(-drawRect.TopLeft()));
      targetOffset = drawRect.TopLeft();
    }

    if (clipPathFrame && !isTrivialClip) {
      Matrix clippedMaskTransform;
      RefPtr<SourceSurface> clipMaskSurface = clipPathFrame->GetClipMask(aContext, aFrame, cssPxToDevPxMatrix,
                                                                         &clippedMaskTransform, maskSurface, maskTransform);

      if (clipMaskSurface) {
        maskSurface = clipMaskSurface;
        maskTransform = clippedMaskTransform;
      }
    }

    if (opacity != 1.0f || svgMaskFrame  || hasValidLayers ||
        (clipPathFrame && !isTrivialClip)) {
      target->PushGroupForBlendBack(gfxContentType::COLOR_ALPHA, opacity, maskSurface, maskTransform);
    }
  }

  /* If this frame has only a trivial clipPath, set up cairo's clipping now so
   * we can just do normal painting and get it clipped appropriately.
   */
  if (clipPathFrame && isTrivialClip) {
    aContext.Save();
    clipPathFrame->ApplyClipPath(aContext, aFrame, cssPxToDevPxMatrix);
  }

  /* Paint the child */
  if (effectProperties.HasValidFilter()) {
    RegularFramePaintCallback callback(aBuilder, aLayerManager,
                                       offsetToUserSpace);

    nsRegion dirtyRegion = aDirtyRect - offsetToBoundingBox;
    gfxMatrix tm = nsSVGIntegrationUtils::GetCSSPxToDevPxMatrix(aFrame);
    nsFilterInstance::PaintFilteredFrame(aFrame, target->GetDrawTarget(),
                                         tm, &callback, &dirtyRegion);
  } else {
    target->SetMatrix(matrixAutoSaveRestore.Matrix());
    BasicLayerManager* basic = static_cast<BasicLayerManager*>(aLayerManager);
    RefPtr<gfxContext> oldCtx = basic->GetTarget();
    basic->SetTarget(target);
    aLayerManager->EndTransaction(FrameLayerBuilder::DrawPaintedLayer, aBuilder);
    basic->SetTarget(oldCtx);
  }

  if (clipPathFrame && isTrivialClip) {
    aContext.Restore();
  }

  /* No more effects, we're done. */
  if (!complexEffects) {
    return;
  }

  if (opacity != 1.0f || svgMaskFrame || hasValidLayers ||
      (clipPathFrame && !isTrivialClip)) {
    target->PopGroupAndBlend();
  }

  if (aFrame->StyleDisplay()->mMixBlendMode != NS_STYLE_BLEND_NORMAL) {
    RefPtr<DrawTarget> targetDT = target->GetDrawTarget();
    target = nullptr;
    RefPtr<SourceSurface> targetSurf = targetDT->Snapshot();

    aContext.SetMatrix(gfxMatrix()); // This will be restored right after.
    RefPtr<gfxPattern> pattern = new gfxPattern(targetSurf, Matrix::Translation(targetOffset.x, targetOffset.y));
    aContext.SetPattern(pattern);
    aContext.Paint();
  }

  aContext.Restore();
}
static IntRect
ComputeMaskGeometry(const nsSVGIntegrationUtils::PaintFramesParams& aParams,
                    const nsStyleSVGReset *svgReset,
                    const nsPoint& aOffsetToUserSpace,
                    const nsTArray<nsSVGMaskFrame *>& aMaskFrames)
{
  gfxContext& ctx = aParams.ctx;
  nsIFrame* frame = aParams.frame;

  // Convert boaderArea and dirtyRect to user space.
  int32_t appUnitsPerDevPixel = frame->PresContext()->AppUnitsPerDevPixel();
  nsRect userSpaceBorderArea = aParams.borderArea - aOffsetToUserSpace;
  nsRect userSpaceDirtyRect = aParams.dirtyRect - aOffsetToUserSpace;

  // Union all mask layer rectangles in user space.
  gfxRect maskInUserSpace;
  for (size_t i = 0; i < aMaskFrames.Length() ; i++) {
    nsSVGMaskFrame* maskFrame = aMaskFrames[i];
    gfxRect currentMaskSurfaceRect;

    if (maskFrame) {
      currentMaskSurfaceRect = maskFrame->GetMaskArea(aParams.frame);
    } else {
      nsCSSRendering::ImageLayerClipState clipState;
      nsCSSRendering::GetImageLayerClip(svgReset->mMask.mLayers[i],
                                       frame,
                                       *frame->StyleBorder(),
                                       userSpaceBorderArea,
                                       userSpaceDirtyRect,
                                       false, /* aWillPaintBorder */
                                       appUnitsPerDevPixel,
                                       &clipState);
      currentMaskSurfaceRect = clipState.mDirtyRectGfx;
    }

    maskInUserSpace = maskInUserSpace.Union(currentMaskSurfaceRect);
  }

  ctx.Save();

  // Clip ctx by both frame's visual overflow rect and mask union.
  gfxRect frameVisualOverflowRect =
    nsLayoutUtils::RectToGfxRect(frame->GetVisualOverflowRectRelativeToSelf(),
                                 appUnitsPerDevPixel);
  ctx.Clip(frameVisualOverflowRect);
  // maskInUserSpace might be empty if all mask references are not resolvable
  // or the size of them are empty. We still need to create a transparent mask
  // before bug 1276834 fixed, so don't clip ctx by an empty rectangle for for
  // now.
  if (!maskInUserSpace.IsEmpty()) {
    ctx.Clip(maskInUserSpace);
  }

  // Get the clip extents in device space.
  ctx.SetMatrix(gfxMatrix());
  gfxRect clippedFrameSurfaceRect = ctx.GetClipExtents();
  clippedFrameSurfaceRect.RoundOut();

  ctx.Restore();

  IntRect result;
  ToRect(clippedFrameSurfaceRect).ToIntRect(&result);
  return mozilla::gfx::Factory::CheckSurfaceSize(result.Size()) ? result
                                                                : IntRect();
}
Пример #15
0
void
DeprecatedTextureHostShmemD3D9::UpdateImpl(const SurfaceDescriptor& aImage,
                                 nsIntRegion *aRegion,
                                 nsIntPoint *aOffset)
{
  MOZ_ASSERT(aImage.type() == SurfaceDescriptor::TShmem ||
             aImage.type() == SurfaceDescriptor::TMemoryImage);
  MOZ_ASSERT(mCompositor, "Must have compositor to update.");

  if (!mCompositor->device()) {
    return;
  }

  AutoOpenSurface openSurf(OPEN_READ_ONLY, aImage);

  nsRefPtr<gfxImageSurface> surf = openSurf.GetAsImage();

  mSize = ToIntSize(surf->GetSize());

  uint32_t bpp = 0;

  _D3DFORMAT format = D3DFMT_A8R8G8B8;
  switch (surf->Format()) {
  case gfxImageFormat::RGB24:
    mFormat = SurfaceFormat::B8G8R8X8;
    format = D3DFMT_X8R8G8B8;
    bpp = 4;
    break;
  case gfxImageFormat::ARGB32:
    mFormat = SurfaceFormat::B8G8R8A8;
    format = D3DFMT_A8R8G8B8;
    bpp = 4;
    break;
  case gfxImageFormat::A8:
    mFormat = SurfaceFormat::A8;
    format = D3DFMT_A8;
    bpp = 1;
    break;
  default:
    NS_ERROR("Bad image format");
  }

  int32_t maxSize = mCompositor->GetMaxTextureSize();
  if (mSize.width <= maxSize && mSize.height <= maxSize) {
    mTexture = DataToTexture(gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager(),
                             surf->Data(), surf->Stride(),
                             mSize, format, bpp);
    if (!mTexture) {
      NS_WARNING("Could not upload texture");
      Reset();
      return;
    }
    mIsTiled = false;
  } else {
    mIsTiled = true;
    uint32_t tileCount = GetRequiredTilesD3D9(mSize.width, maxSize) *
                         GetRequiredTilesD3D9(mSize.height, maxSize);
    mTileTextures.resize(tileCount);

    for (uint32_t i = 0; i < tileCount; i++) {
      IntRect tileRect = GetTileRect(i);
      unsigned char* data = surf->Data() +
                            tileRect.y * surf->Stride() +
                            tileRect.x * bpp;
      mTileTextures[i] = DataToTexture(gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager(),
                                       data,
                                       surf->Stride(),
                                       tileRect.Size(),
                                       format,
                                       bpp);
      if (!mTileTextures[i]) {
        NS_WARNING("Could not upload texture");
        Reset();
        return;
      }
    }
  }
}
void
nsSVGIntegrationUtils::PaintFramesWithEffects(const PaintFramesParams& aParams)
{
#ifdef DEBUG
  NS_ASSERTION(!(aParams.frame->GetStateBits() & NS_FRAME_SVG_LAYOUT) ||
               (NS_SVGDisplayListPaintingEnabled() &&
                !(aParams.frame->GetStateBits() & NS_FRAME_IS_NONDISPLAY)),
               "Should not use nsSVGIntegrationUtils on this SVG frame");
#endif

  /* SVG defines the following rendering model:
   *
   *  1. Render geometry
   *  2. Apply filter
   *  3. Apply clipping, masking, group opacity
   *
   * We follow this, but perform a couple of optimizations:
   *
   * + Use cairo's clipPath when representable natively (single object
   *   clip region).
   *
   * + Merge opacity and masking if both used together.
   */
  nsIFrame* frame = aParams.frame;
  const nsIContent* content = frame->GetContent();
  bool hasSVGLayout = (frame->GetStateBits() & NS_FRAME_SVG_LAYOUT);
  if (hasSVGLayout) {
    nsISVGChildFrame *svgChildFrame = do_QueryFrame(frame);
    if (!svgChildFrame || !frame->GetContent()->IsSVGElement()) {
      NS_ASSERTION(false, "why?");
      return;
    }
    if (!static_cast<const nsSVGElement*>(content)->HasValidDimensions()) {
      return; // The SVG spec says not to draw _anything_
    }
  }

  float opacity = frame->StyleEffects()->mOpacity;
  if (opacity == 0.0f) {
    return;
  }
  if (opacity != 1.0f &&
      (nsSVGUtils::CanOptimizeOpacity(frame) ||
       aParams.callerPaintsOpacity)) {
    opacity = 1.0f;
  }
  MOZ_ASSERT(!nsSVGUtils::CanOptimizeOpacity(frame) || !aParams.callerPaintsOpacity,
             "How can we be optimizing the opacity into the svg as well as having the caller paint it?");

  /* Properties are added lazily and may have been removed by a restyle,
     so make sure all applicable ones are set again. */
  nsIFrame* firstFrame =
    nsLayoutUtils::FirstContinuationOrIBSplitSibling(frame);
  nsSVGEffects::EffectProperties effectProperties =
    nsSVGEffects::GetEffectProperties(firstFrame);

  bool isOK = effectProperties.HasNoFilterOrHasValidFilter();
  nsSVGClipPathFrame *clipPathFrame = effectProperties.GetClipPathFrame(&isOK);

  bool isTrivialClip = clipPathFrame ? clipPathFrame->IsTrivial() : true;
  gfxContext& context = aParams.ctx;
  DrawTarget* drawTarget = context.GetDrawTarget();
  gfxContextMatrixAutoSaveRestore matrixAutoSaveRestore(&context);

  nsPoint firstFrameOffset = GetOffsetToBoundingBox(firstFrame);
  nsPoint offsetToBoundingBox = aParams.builder->ToReferenceFrame(firstFrame) - firstFrameOffset;
  if (!firstFrame->IsFrameOfType(nsIFrame::eSVG)) {
    /* Snap the offset if the reference frame is not a SVG frame,
     * since other frames will be snapped to pixel when rendering. */
    offsetToBoundingBox = nsPoint(
      frame->PresContext()->RoundAppUnitsToNearestDevPixels(offsetToBoundingBox.x),
      frame->PresContext()->RoundAppUnitsToNearestDevPixels(offsetToBoundingBox.y));
  }

  // After applying only "offsetToBoundingBox", aCtx would have its origin at
  // the top left corner of frame's bounding box (over all continuations).
  // However, SVG painting needs the origin to be located at the origin of the
  // SVG frame's "user space", i.e. the space in which, for example, the
  // frame's BBox lives.
  // SVG geometry frames and foreignObject frames apply their own offsets, so
  // their position is relative to their user space. So for these frame types,
  // if we want aCtx to be in user space, we first need to subtract the
  // frame's position so that SVG painting can later add it again and the
  // frame is painted in the right place.

  gfxPoint toUserSpaceGfx = nsSVGUtils::FrameSpaceInCSSPxToUserSpaceOffset(frame);
  nsPoint toUserSpace(nsPresContext::CSSPixelsToAppUnits(float(toUserSpaceGfx.x)),
                      nsPresContext::CSSPixelsToAppUnits(float(toUserSpaceGfx.y)));
  nsPoint offsetToUserSpace = offsetToBoundingBox - toUserSpace;

  NS_ASSERTION(hasSVGLayout || offsetToBoundingBox == offsetToUserSpace,
               "For non-SVG frames there shouldn't be any additional offset");

  gfxPoint devPixelOffsetToUserSpace =
    nsLayoutUtils::PointToGfxPoint(offsetToUserSpace,
                                   frame->PresContext()->AppUnitsPerDevPixel());
  context.SetMatrix(context.CurrentMatrix().Translate(devPixelOffsetToUserSpace));

  gfxMatrix cssPxToDevPxMatrix = GetCSSPxToDevPxMatrix(frame);

  const nsStyleSVGReset *svgReset = firstFrame->StyleSVGReset();
  nsTArray<nsSVGMaskFrame *> maskFrames = effectProperties.GetMaskFrames();
  // For a HTML doc:
  //   According to css-masking spec, always create a mask surface when we
  //   have any item in maskFrame even if all of those items are
  //   non-resolvable <mask-sources> or <images>, we still need to create a
  //   transparent black mask layer under this condition.
  // For a SVG doc:
  //   SVG 1.1 say that  if we fail to resolve a mask, we should draw the
  //   object unmasked.
  nsIDocument* currentDoc = frame->PresContext()->Document();
  bool shouldGenerateMaskLayer = currentDoc->IsSVGDocument()
                                 ? maskFrames.Length() == 1 && maskFrames[0]
                                 : maskFrames.Length() > 0;

  // These are used if we require a temporary surface for a custom blend mode.
  RefPtr<gfxContext> target = &aParams.ctx;
  IntPoint targetOffset;

  bool complexEffects = false;
  /* Check if we need to do additional operations on this child's
   * rendering, which necessitates rendering into another surface. */
  if (opacity != 1.0f ||  (clipPathFrame && !isTrivialClip)
      || frame->StyleEffects()->mMixBlendMode != NS_STYLE_BLEND_NORMAL
      || shouldGenerateMaskLayer) {
    complexEffects = true;

    context.Save();
    nsRect clipRect =
      frame->GetVisualOverflowRectRelativeToSelf() + toUserSpace;
    context.Clip(NSRectToSnappedRect(clipRect,
                                  frame->PresContext()->AppUnitsPerDevPixel(),
                                  *drawTarget));
    Matrix maskTransform;
    RefPtr<SourceSurface> maskSurface;

    if (shouldGenerateMaskLayer) {
      GenerateMaskSurface(aParams, opacity, firstFrame->StyleContext(),
                          maskFrames, offsetToUserSpace,
                          maskTransform, maskSurface);
    }

    if (shouldGenerateMaskLayer && !maskSurface) {
      // Entire surface is clipped out.
      context.Restore();
      return;
    }

    if (frame->StyleEffects()->mMixBlendMode != NS_STYLE_BLEND_NORMAL) {
      // Create a temporary context to draw to so we can blend it back with
      // another operator.
      gfxRect clipRect;
      {
        gfxContextMatrixAutoSaveRestore matRestore(&context);

        context.SetMatrix(gfxMatrix());
        clipRect = context.GetClipExtents();
      }

      IntRect drawRect = RoundedOut(ToRect(clipRect));

      RefPtr<DrawTarget> targetDT = context.GetDrawTarget()->CreateSimilarDrawTarget(drawRect.Size(), SurfaceFormat::B8G8R8A8);
      if (!targetDT || !targetDT->IsValid()) {
        context.Restore();
        return;
      }
      target = gfxContext::CreateOrNull(targetDT);
      MOZ_ASSERT(target); // already checked the draw target above
      target->SetMatrix(context.CurrentMatrix() * gfxMatrix::Translation(-drawRect.TopLeft()));
      targetOffset = drawRect.TopLeft();
    }

    if (clipPathFrame && !isTrivialClip) {
      Matrix clippedMaskTransform;
      RefPtr<SourceSurface> clipMaskSurface = clipPathFrame->GetClipMask(context, frame, cssPxToDevPxMatrix,
                                                                         &clippedMaskTransform, maskSurface, maskTransform);

      if (clipMaskSurface) {
        maskSurface = clipMaskSurface;
        maskTransform = clippedMaskTransform;
      }
    }

    if (opacity != 1.0f || shouldGenerateMaskLayer ||
        (clipPathFrame && !isTrivialClip)) {
      target->PushGroupForBlendBack(gfxContentType::COLOR_ALPHA, opacity, maskSurface, maskTransform);
    }
  }

  /* If this frame has only a trivial clipPath, set up cairo's clipping now so
   * we can just do normal painting and get it clipped appropriately.
   */
  if (clipPathFrame && isTrivialClip) {
    context.Save();
    clipPathFrame->ApplyClipPath(context, frame, cssPxToDevPxMatrix);
  } else if (!clipPathFrame && svgReset->HasClipPath()) {
    context.Save();
    nsCSSClipPathInstance::ApplyBasicShapeClip(context, frame);
  }

  /* Paint the child */
  if (effectProperties.HasValidFilter()) {
    RegularFramePaintCallback callback(aParams.builder, aParams.layerManager,
                                       offsetToUserSpace);

    nsRegion dirtyRegion = aParams.dirtyRect - offsetToBoundingBox;
    gfxMatrix tm = nsSVGIntegrationUtils::GetCSSPxToDevPxMatrix(frame);
    nsFilterInstance::PaintFilteredFrame(frame, target->GetDrawTarget(),
                                         tm, &callback, &dirtyRegion);
  } else {
    target->SetMatrix(matrixAutoSaveRestore.Matrix());
    BasicLayerManager* basic = static_cast<BasicLayerManager*>(aParams.layerManager);
    RefPtr<gfxContext> oldCtx = basic->GetTarget();
    basic->SetTarget(target);
    aParams.layerManager->EndTransaction(FrameLayerBuilder::DrawPaintedLayer,
                                          aParams.builder);
    basic->SetTarget(oldCtx);
  }

  if ((clipPathFrame && isTrivialClip) ||
      (!clipPathFrame && svgReset->HasClipPath())) {
    context.Restore();
  }

  /* No more effects, we're done. */
  if (!complexEffects) {
    return;
  }

  if (opacity != 1.0f || shouldGenerateMaskLayer ||
      (clipPathFrame && !isTrivialClip)) {
    target->PopGroupAndBlend();
  }

  if (frame->StyleEffects()->mMixBlendMode != NS_STYLE_BLEND_NORMAL) {
    RefPtr<DrawTarget> targetDT = target->GetDrawTarget();
    target = nullptr;
    RefPtr<SourceSurface> targetSurf = targetDT->Snapshot();

    context.SetMatrix(gfxMatrix()); // This will be restored right after.
    RefPtr<gfxPattern> pattern = new gfxPattern(targetSurf, Matrix::Translation(targetOffset.x, targetOffset.y));
    context.SetPattern(pattern);
    context.Paint();
  }

  context.Restore();
}
Пример #17
0
/* static */ void
gfxAlphaBoxBlur::BlurRectangle(gfxContext* aDestinationCtx,
                               const gfxRect& aRect,
                               const RectCornerRadii* aCornerRadii,
                               const gfxPoint& aBlurStdDev,
                               const Color& aShadowColor,
                               const gfxRect& aDirtyRect,
                               const gfxRect& aSkipRect)
{
  IntSize blurRadius = CalculateBlurRadius(aBlurStdDev);
  bool mirrorCorners = !aCornerRadii || aCornerRadii->AreRadiiSame();

  IntRect rect = RoundedToInt(ToRect(aRect));
  IntMargin blurMargin;
  IntMargin slice;
  IntSize minSize;
  RefPtr<SourceSurface> boxShadow = GetBlur(aDestinationCtx,
                                            rect.Size(), blurRadius,
                                            aCornerRadii, aShadowColor, mirrorCorners,
                                            blurMargin, slice, minSize);
  if (!boxShadow) {
    return;
  }

  DrawTarget* destDrawTarget = aDestinationCtx->GetDrawTarget();
  destDrawTarget->PushClipRect(ToRect(aDirtyRect));

  // Copy the right parts from boxShadow into destDrawTarget. The middle parts
  // will be stretched, border-image style.

  Rect srcOuter(Point(blurMargin.left, blurMargin.top), Size(minSize));
  Rect srcInner(srcOuter);
  srcOuter.Inflate(Margin(blurMargin));
  srcInner.Deflate(Margin(slice));

  Rect dstOuter(rect);
  Rect dstInner(rect);
  dstOuter.Inflate(Margin(blurMargin));
  dstInner.Deflate(Margin(slice));

  Rect skipRect = ToRect(aSkipRect);

  if (minSize == rect.Size()) {
    // The target rect is smaller than the minimal size so just draw the surface
    if (mirrorCorners) {
      DrawMirroredBoxShadow(destDrawTarget, boxShadow, dstOuter);
    } else {
      destDrawTarget->DrawSurface(boxShadow, dstOuter, srcOuter);
    }
  } else {
    if (mirrorCorners) {
      DrawMirroredMinBoxShadow(destDrawTarget, boxShadow, dstOuter, dstInner,
                               srcOuter, srcInner, skipRect, true);
    } else {
      DrawMinBoxShadow(destDrawTarget, boxShadow, dstOuter, dstInner,
                       srcOuter, srcInner, skipRect, true);
    }
  }

  // A note about anti-aliasing and seems between adjacent parts:
  // We don't explicitly disable anti-aliasing in the DrawSurface calls above,
  // so if there's a transform on destDrawTarget that is not pixel-aligned,
  // there will be seams between adjacent parts of the box-shadow. It's hard to
  // avoid those without the use of an intermediate surface.
  // You might think that we could avoid those by just turning of AA, but there
  // is a problem with that: Box-shadow rendering needs to clip out the
  // element's border box, and we'd like that clip to have anti-aliasing -
  // especially if the element has rounded corners! So we can't do that unless
  // we have a way to say "Please anti-alias the clip, but don't antialias the
  // destination rect of the DrawSurface call".
  // On OS X there is an additional problem with turning off AA: CoreGraphics
  // will not just fill the pixels that have their pixel center inside the
  // filled shape. Instead, it will fill all the pixels which are partially
  // covered by the shape. So for pixels on the edge between two adjacent parts,
  // all those pixels will be painted to by both parts, which looks very bad.

  destDrawTarget->PopClip();
}
static void
GenerateMaskSurface(const nsSVGIntegrationUtils::PaintFramesParams& aParams,
                    float aOpacity, nsStyleContext* aSC,
                    nsSVGEffects::EffectProperties& aEffectProperties,
                    const gfxPoint& aOffest, Matrix& aOutMaskTransform,
                    RefPtr<SourceSurface>& aOutMaskSurface)
{
  const nsStyleSVGReset *svgReset = aSC->StyleSVGReset();
  MOZ_ASSERT(HasMaskToDraw(svgReset, aEffectProperties));

  nsTArray<nsSVGMaskFrame *> svgMaskFrames = aEffectProperties.GetMaskFrames();
  MOZ_ASSERT(svgMaskFrames.Length() == svgReset->mMask.mImageCount);

  gfxMatrix cssPxToDevPxMatrix =
    nsSVGIntegrationUtils::GetCSSPxToDevPxMatrix(aParams.frame);

  gfxContext& ctx = aParams.ctx;

  // There is only one mask. And that mask is a SVG mask.
  if ((svgMaskFrames.Length() == 1) && svgMaskFrames[0]) {
    aOutMaskSurface =
      svgMaskFrames[0]->GetMaskForMaskedFrame(&ctx, aParams.frame,
                                              cssPxToDevPxMatrix, aOpacity,
                                              &aOutMaskTransform,
                                              svgReset->mMask.mLayers[0].mMaskMode);
    return;
  }

  ctx.Save();
  ctx.SetMatrix(gfxMatrix());
  gfxRect clipExtents = ctx.GetClipExtents();
  IntRect maskSurfaceRect = RoundedOut(ToRect(clipExtents));
  ctx.Restore();

  // Mask composition result on CoreGraphic::A8 surface is not correct
  // when mask-mode is not add(source over). Switch to skia when CG backend
  // detected.
  RefPtr<DrawTarget> maskDT =
    (ctx.GetDrawTarget()->GetBackendType() == BackendType::COREGRAPHICS)
    ? Factory::CreateDrawTarget(BackendType::SKIA, maskSurfaceRect.Size(),
                                SurfaceFormat::A8)
    : ctx.GetDrawTarget()->CreateSimilarDrawTarget(maskSurfaceRect.Size(),
                                                   SurfaceFormat::A8);
  RefPtr<gfxContext> maskContext = gfxContext::ForDrawTarget(maskDT);

  // Set ctx's matrix on maskContext, offset by the maskSurfaceRect's position.
  // This makes sure that we combine the masks in device space.
  gfxMatrix maskSurfaceMatrix =
    ctx.CurrentMatrix() * gfxMatrix::Translation(-maskSurfaceRect.TopLeft());
  maskContext->SetMatrix(maskSurfaceMatrix);

  // Multiple SVG masks interleave with image mask. Paint each layer onto maskDT
  // one at a time.
  for (int i = svgMaskFrames.Length() - 1; i >= 0 ; i--) {
    nsSVGMaskFrame *maskFrame = svgMaskFrames[i];

    CompositionOp compositionOp = (i == int(svgMaskFrames.Length() - 1))
      ? CompositionOp::OP_OVER
      : nsCSSRendering::GetGFXCompositeMode(svgReset->mMask.mLayers[i].mComposite);

    // maskFrame != nullptr means we get a SVG mask.
    // maskFrame == nullptr means we get an image mask.
    if (maskFrame) {
      Matrix svgMaskMatrix;
      RefPtr<SourceSurface> svgMask =
        maskFrame->GetMaskForMaskedFrame(maskContext, aParams.frame,
                                         cssPxToDevPxMatrix, aOpacity,
                                         &svgMaskMatrix,
                                         svgReset->mMask.mLayers[i].mMaskMode);
      if (svgMask) {
        gfxContextMatrixAutoSaveRestore matRestore(maskContext);

        maskContext->Multiply(ThebesMatrix(svgMaskMatrix));
        Rect drawRect = IntRectToRect(IntRect(IntPoint(0, 0), svgMask->GetSize()));
        maskDT->DrawSurface(svgMask, drawRect, drawRect, DrawSurfaceOptions(),
                            DrawOptions(1.0f, compositionOp));
      }
    } else {
      gfxContextMatrixAutoSaveRestore matRestore(maskContext);

      maskContext->Multiply(gfxMatrix::Translation(-aOffest));
      nsRenderingContext rc(maskContext);
      nsCSSRendering::PaintBGParams  params =
        nsCSSRendering::PaintBGParams::ForSingleLayer(*aParams.frame->PresContext(),
                                                      rc, aParams.dirtyRect,
                                                      aParams.borderArea,
                                                      aParams.frame,
                                                      aParams.builder->GetBackgroundPaintFlags() |
                                                      nsCSSRendering::PAINTBG_MASK_IMAGE,
                                                      i, compositionOp);

      // FIXME We should use the return value, see bug 1258510.
      Unused << nsCSSRendering::PaintBackgroundWithSC(params, aSC,
                                                      *aParams.frame->StyleBorder());
    }
  }

  aOutMaskTransform = ToMatrix(maskSurfaceMatrix);
  if (!aOutMaskTransform.Invert()) {
    return;
  }

  aOutMaskSurface = maskDT->Snapshot();
}
Пример #19
0
void
DeprecatedTextureHostSystemMemD3D9::UpdateImpl(const SurfaceDescriptor& aImage,
                                     nsIntRegion *aRegion,
                                     nsIntPoint *aOffset)
{
  MOZ_ASSERT(aImage.type() == SurfaceDescriptor::TSurfaceDescriptorD3D9);
  MOZ_ASSERT(mCompositor, "Must have compositor to update.");

  if (!mCompositor->device()) {
    return;
  }

  IDirect3DTexture9* texture =
    reinterpret_cast<IDirect3DTexture9*>(aImage.get_SurfaceDescriptorD3D9().texture());

  if (!texture) {
    Reset();
    return;
  }

  D3DSURFACE_DESC desc;
  texture->GetLevelDesc(0, &desc);
  HRESULT hr = texture->GetLevelDesc(0, &desc);
  if (FAILED(hr)) {
    Reset();
    return;
  }

  mSize.width = desc.Width;
  mSize.height = desc.Height;

  _D3DFORMAT format = desc.Format;
  uint32_t bpp = 0;
  switch (format) {
  case D3DFMT_X8R8G8B8:
    mFormat = SurfaceFormat::B8G8R8X8;
    bpp = 4;
    break;
  case D3DFMT_A8R8G8B8:
    mFormat = SurfaceFormat::B8G8R8A8;
    bpp = 4;
    break;
  case D3DFMT_A8:
    mFormat = SurfaceFormat::A8;
    bpp = 1;
    break;
  default:
    NS_ERROR("Bad image format");
  }

  int32_t maxSize = mCompositor->GetMaxTextureSize();
  if (mSize.width <= maxSize && mSize.height <= maxSize) {
    mIsTiled = false;

    mTexture = TextureToTexture(gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager(),
                                texture, mSize, format);
    if (!mTexture) {
      NS_WARNING("Could not upload texture");
      Reset();
      return;
    }
  } else {
    mIsTiled = true;

    uint32_t tileCount = GetRequiredTilesD3D9(mSize.width, maxSize) *
                         GetRequiredTilesD3D9(mSize.height, maxSize);
    mTileTextures.resize(tileCount);

    for (uint32_t i = 0; i < tileCount; i++) {
      IntRect tileRect = GetTileRect(i);
      RECT d3dTileRect;
      d3dTileRect.left = tileRect.x;
      d3dTileRect.top = tileRect.y;
      d3dTileRect.right = tileRect.XMost();
      d3dTileRect.bottom = tileRect.YMost();
      D3DLOCKED_RECT lockedRect;
      texture->LockRect(0, &lockedRect, &d3dTileRect, 0);
      mTileTextures[i] = DataToTexture(gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager(),
                                       reinterpret_cast<unsigned char*>(lockedRect.pBits),
                                       lockedRect.Pitch,
                                       tileRect.Size(),
                                       format,
                                       bpp);
      texture->UnlockRect(0);
      if (!mTileTextures[i]) {
        NS_WARNING("Could not upload texture");
        Reset();
        return;
      }
    }
  }
}
Пример #20
0
void
DeprecatedTextureHostDIB::UpdateImpl(const SurfaceDescriptor& aImage,
                                     nsIntRegion *aRegion,
                                     nsIntPoint *aOffset)
{
  MOZ_ASSERT(aImage.type() == SurfaceDescriptor::TSurfaceDescriptorDIB);
  MOZ_ASSERT(mCompositor, "Must have compositor to update.");

  if (!mCompositor->device()) {
    return;
  }

  // We added an extra ref for transport, so we shouldn't AddRef now.
  nsRefPtr<gfxWindowsSurface> surf =
    dont_AddRef(reinterpret_cast<gfxWindowsSurface*>(aImage.get_SurfaceDescriptorDIB().surface()));

  mSize = ToIntSize(surf->GetSize());

  uint32_t bpp = 0;

  _D3DFORMAT format = D3DFMT_A8R8G8B8;
  switch (gfxPlatform::GetPlatform()->OptimalFormatForContent(surf->GetContentType())) {
  case gfxImageFormat::RGB24:
    mFormat = SurfaceFormat::B8G8R8X8;
    format = D3DFMT_X8R8G8B8;
    bpp = 4;
    break;
  case gfxImageFormat::ARGB32:
    mFormat = SurfaceFormat::B8G8R8A8;
    format = D3DFMT_A8R8G8B8;
    bpp = 4;
    break;
  case gfxImageFormat::A8:
    mFormat = SurfaceFormat::A8;
    format = D3DFMT_A8;
    bpp = 1;
    break;
  default:
    NS_ERROR("Bad image format");
  }

  int32_t maxSize = mCompositor->GetMaxTextureSize();
  if (mSize.width <= maxSize && mSize.height <= maxSize) {
    mTexture = SurfaceToTexture(gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager(),
                                surf, mSize, format);
    if (!mTexture) {
      NS_WARNING("Could not upload texture");
      Reset();
      return;
    }
    mIsTiled = false;
  } else {
    mIsTiled = true;

    uint32_t tileCount = GetRequiredTilesD3D9(mSize.width, maxSize) *
                         GetRequiredTilesD3D9(mSize.height, maxSize);
    mTileTextures.resize(tileCount);

    for (uint32_t i = 0; i < tileCount; i++) {
      IntRect tileRect = GetTileRect(i);
      nsRefPtr<gfxImageSurface> imgSurface = surf->GetAsImageSurface();
      unsigned char* data = imgSurface->Data() +
                            tileRect.y * imgSurface->Stride() +
                            tileRect.x * bpp;
      mTileTextures[i] = DataToTexture(gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager(),
                                       data,
                                       imgSurface->Stride(),
                                       tileRect.Size(),
                                       format,
                                       bpp);
      if (!mTileTextures[i]) {
        NS_WARNING("Could not upload texture");
        Reset();
        return;
      }
    }
  }
}
Пример #21
0
/* static */
already_AddRefed<VideoData>
VideoData::Create(const VideoInfo& aInfo,
                  ImageContainer* aContainer,
                  int64_t aOffset,
                  int64_t aTime,
                  int64_t aDuration,
                  mozilla::layers::TextureClient* aBuffer,
                  bool aKeyframe,
                  int64_t aTimecode,
                  const IntRect& aPicture)
{
  if (!aContainer) {
    // Create a dummy VideoData with no image. This gives us something to
    // send to media streams if necessary.
    RefPtr<VideoData> v(new VideoData(aOffset,
                                        aTime,
                                        aDuration,
                                        aKeyframe,
                                        aTimecode,
                                        aInfo.mDisplay,
                                        0));
    return v.forget();
  }

  // The following situations could be triggered by invalid input
  if (aPicture.width <= 0 || aPicture.height <= 0) {
    NS_WARNING("Empty picture rect");
    return nullptr;
  }

  // Ensure the picture size specified in the headers can be extracted out of
  // the frame we've been supplied without indexing out of bounds.
  CheckedUint32 xLimit = aPicture.x + CheckedUint32(aPicture.width);
  CheckedUint32 yLimit = aPicture.y + CheckedUint32(aPicture.height);
  if (!xLimit.isValid() || !yLimit.isValid())
  {
    // The specified picture dimensions can't be contained inside the video
    // frame, we'll stomp memory if we try to copy it. Fail.
    NS_WARNING("Overflowing picture rect");
    return nullptr;
  }

  RefPtr<VideoData> v(new VideoData(aOffset,
                                      aTime,
                                      aDuration,
                                      aKeyframe,
                                      aTimecode,
                                      aInfo.mDisplay,
                                      0));

  v->mImage = aContainer->CreateImage(ImageFormat::GRALLOC_PLANAR_YCBCR);
  if (!v->mImage) {
    return nullptr;
  }
  NS_ASSERTION(v->mImage->GetFormat() == ImageFormat::GRALLOC_PLANAR_YCBCR,
               "Wrong format?");
  typedef mozilla::layers::GrallocImage GrallocImage;
  GrallocImage* videoImage = static_cast<GrallocImage*>(v->mImage.get());
  GrallocImage::GrallocData data;

  data.mPicSize = aPicture.Size();
  data.mGraphicBuffer = aBuffer;

  if (!videoImage->SetData(data)) {
    return nullptr;
  }

  return v.forget();
}
Пример #22
0
already_AddRefed<SourceSurface>
nsSVGClipPathFrame::GetClipMask(gfxContext& aReferenceContext,
                                nsIFrame* aClippedFrame,
                                const gfxMatrix& aMatrix,
                                Matrix* aMaskTransform,
                                SourceSurface* aExtraMask,
                                const Matrix& aExtraMasksTransform)
{
  MOZ_ASSERT(!IsTrivial(), "Caller needs to use ApplyClipPath");

  DrawTarget& aReferenceDT = *aReferenceContext.GetDrawTarget();

  // A clipPath can reference another clipPath.  We re-enter this method for
  // each clipPath in a reference chain, so here we limit chain length:
  static int16_t sRefChainLengthCounter = AutoReferenceLimiter::notReferencing;
  AutoReferenceLimiter
    refChainLengthLimiter(&sRefChainLengthCounter,
                          MAX_SVG_CLIP_PATH_REFERENCE_CHAIN_LENGTH);
  if (!refChainLengthLimiter.Reference()) {
    return nullptr; // Reference chain is too long!
  }

  // And to prevent reference loops we check that this clipPath only appears
  // once in the reference chain (if any) that we're currently processing:
  AutoReferenceLimiter refLoopDetector(&mReferencing, 1);
  if (!refLoopDetector.Reference()) {
    return nullptr; // Reference loop!
  }

  IntRect devSpaceClipExtents;
  {
    gfxContextMatrixAutoSaveRestore autoRestoreMatrix(&aReferenceContext);

    aReferenceContext.SetMatrix(gfxMatrix());
    gfxRect rect = aReferenceContext.GetClipExtents();
    devSpaceClipExtents = RoundedOut(ToRect(rect));
    if (devSpaceClipExtents.IsEmpty()) {
      // We don't need to create a mask surface, all drawing is clipped anyway.
      return nullptr;
    }
  }

  RefPtr<DrawTarget> maskDT =
    aReferenceDT.CreateSimilarDrawTarget(devSpaceClipExtents.Size(),
                                         SurfaceFormat::A8);

  gfxMatrix mat = aReferenceContext.CurrentMatrix() *
                    gfxMatrix::Translation(-devSpaceClipExtents.TopLeft());

  // Paint this clipPath's contents into maskDT:
  {
    RefPtr<gfxContext> ctx = new gfxContext(maskDT);
    ctx->SetMatrix(mat);

    // We need to set mMatrixForChildren here so that under the PaintSVG calls
    // on our children (below) our GetCanvasTM() method will return the correct
    // transform.
    mMatrixForChildren = GetClipPathTransform(aClippedFrame) * aMatrix;

    // Check if this clipPath is itself clipped by another clipPath:
    nsSVGClipPathFrame* clipPathThatClipsClipPath =
      nsSVGEffects::GetEffectProperties(this).GetClipPathFrame(nullptr);
    bool clippingOfClipPathRequiredMasking;
    if (clipPathThatClipsClipPath) {
      ctx->Save();
      clippingOfClipPathRequiredMasking = !clipPathThatClipsClipPath->IsTrivial();
      if (!clippingOfClipPathRequiredMasking) {
        clipPathThatClipsClipPath->ApplyClipPath(*ctx, aClippedFrame, aMatrix);
      } else {
        Matrix maskTransform;
        RefPtr<SourceSurface> mask =
          clipPathThatClipsClipPath->GetClipMask(*ctx, aClippedFrame,
                                                 aMatrix, &maskTransform);
        ctx->PushGroupForBlendBack(gfxContentType::ALPHA, 1.0,
                                   mask, maskTransform);
        // The corresponding PopGroupAndBlend call below will mask the
        // blend using |mask|.
      }
    }

    // Paint our children into the mask:
    for (nsIFrame* kid = mFrames.FirstChild(); kid;
         kid = kid->GetNextSibling()) {
      nsISVGChildFrame* SVGFrame = do_QueryFrame(kid);
      if (SVGFrame) {
        // The CTM of each frame referencing us can be different.
        SVGFrame->NotifySVGChanged(nsISVGChildFrame::TRANSFORM_CHANGED);

        bool isOK = true;
        // Children of this clipPath may themselves be clipped.
        nsSVGClipPathFrame *clipPathThatClipsChild =
          nsSVGEffects::GetEffectProperties(kid).GetClipPathFrame(&isOK);
        if (!isOK) {
          continue;
        }

        bool childsClipPathRequiresMasking;

        if (clipPathThatClipsChild) {
          childsClipPathRequiresMasking = !clipPathThatClipsChild->IsTrivial();
          ctx->Save();
          if (!childsClipPathRequiresMasking) {
            clipPathThatClipsChild->ApplyClipPath(*ctx, aClippedFrame, aMatrix);
          } else {
            Matrix maskTransform;
            RefPtr<SourceSurface> mask =
              clipPathThatClipsChild->GetClipMask(*ctx, aClippedFrame,
                                                  aMatrix, &maskTransform);
            ctx->PushGroupForBlendBack(gfxContentType::ALPHA, 1.0,
                                       mask, maskTransform);
            // The corresponding PopGroupAndBlend call below will mask the
            // blend using |mask|.
          }
        }

        gfxMatrix toChildsUserSpace = mMatrixForChildren;
        nsIFrame* child = do_QueryFrame(SVGFrame);
        nsIContent* childContent = child->GetContent();
        if (childContent->IsSVGElement()) {
          toChildsUserSpace =
            static_cast<const nsSVGElement*>(childContent)->
              PrependLocalTransformsTo(mMatrixForChildren, eUserSpaceToParent);
        }

        // Our children have NS_STATE_SVG_CLIPPATH_CHILD set on them, and
        // nsSVGPathGeometryFrame::Render checks for that state bit and paints
        // only the geometry (opaque black) if set.
        SVGFrame->PaintSVG(*ctx, toChildsUserSpace);

        if (clipPathThatClipsChild) {
          if (childsClipPathRequiresMasking) {
            ctx->PopGroupAndBlend();
          }
          ctx->Restore();
        }
      }
    }


    if (clipPathThatClipsClipPath) {
      if (clippingOfClipPathRequiredMasking) {
        ctx->PopGroupAndBlend();
      }
      ctx->Restore();
    }
  }

  // Moz2D transforms in the opposite direction to Thebes
  mat.Invert();

  if (aExtraMask) {
    // We could potentially due this more efficiently with OPERATOR_IN
    // but that operator does not work well on CG or D2D
    RefPtr<SourceSurface> currentMask = maskDT->Snapshot();
    Matrix transform = maskDT->GetTransform();
    maskDT->SetTransform(Matrix());
    maskDT->ClearRect(Rect(0, 0,
                           devSpaceClipExtents.width,
                           devSpaceClipExtents.height));
    maskDT->SetTransform(aExtraMasksTransform * transform);
    // draw currentMask with the inverse of the transform that we just so that
    // it ends up in the same spot with aExtraMask transformed by aExtraMasksTransform
    maskDT->MaskSurface(SurfacePattern(currentMask, ExtendMode::CLAMP, aExtraMasksTransform.Inverse() * ToMatrix(mat)),
                        aExtraMask,
                        Point(0, 0));
  }

  *aMaskTransform = ToMatrix(mat);
  return maskDT->Snapshot();
}
Пример #23
0
already_AddRefed<mozilla::gfx::SourceSurface>
gfxAlphaBoxBlur::GetInsetBlur(IntMargin& aExtendDestBy,
                              IntMargin& aSlice,
                              const Rect aDestinationRect,
                              const Rect aShadowClipRect,
                              const IntSize& aBlurRadius,
                              const IntSize& aSpreadRadius,
                              const RectCornerRadii& aInnerClipRadii,
                              const Color& aShadowColor,
                              const bool& aHasBorderRadius,
                              const Point aShadowOffset,
                              bool& aMovedOffset,
                              DrawTarget* aDestDrawTarget)
{
  if (!gBlurCache) {
    gBlurCache = new BlurCache();
  }

  IntRect outerRect;
  IntRect innerRect;
  ComputeRectsForInsetBoxShadow(aBlurRadius, aSpreadRadius,
                                outerRect, innerRect,
                                aSlice, aDestinationRect,
                                aShadowClipRect, aHasBorderRadius,
                                aInnerClipRadii);

  // If we have a shadow offset larger than the min rect,
  // there's no clean way we can properly create a min rect with the offset
  // in the correct place and still render correctly.  In those cases,
  // fallback to just rendering the dest rect as is.
  bool useDestRect = (std::abs(aShadowOffset.x) > aSlice.left) ||
                     (std::abs(aShadowOffset.y) > aSlice.top);
  aMovedOffset = false;
  if (useDestRect) {
    aDestinationRect.ToIntRect(&outerRect);
    aShadowClipRect.ToIntRect(&innerRect);
    aMovedOffset = true;
  }

  BlurCacheData* cached =
      gBlurCache->LookupInsetBoxShadow(outerRect.Size(), innerRect.Size(),
                                       aBlurRadius, aSpreadRadius,
                                       &aInnerClipRadii, aShadowColor,
                                       aHasBorderRadius,
                                       aDestDrawTarget->GetBackendType());
  if (cached && !useDestRect) {
    aExtendDestBy = cached->mExtendDest;
    // Need to extend it twice: once for the outer rect and once for the inner rect.
    aSlice += aExtendDestBy;
    aSlice += aExtendDestBy;

    // So we don't forget the actual cached blur
    RefPtr<SourceSurface> cachedBlur = cached->mBlur;
    return cachedBlur.forget();
  }

  // Dirty rect and skip rect are null for the min inset shadow.
  // When rendering inset box shadows, we respect the spread radius by changing
  //  the shape of the unblurred shadow, and can pass a spread radius of zero here.
  IntSize zeroSpread(0, 0);
  gfxContext* minGfxContext = Init(ThebesRect(outerRect),
                                   zeroSpread, aBlurRadius, nullptr, nullptr);
  if (!minGfxContext) {
    return nullptr;
  }

  DrawTarget* minDrawTarget = minGfxContext->GetDrawTarget();
  RefPtr<Path> maskPath =
    GetBoxShadowInsetPath(minDrawTarget, IntRectToRect(outerRect),
                          IntRectToRect(innerRect), aHasBorderRadius,
                          aInnerClipRadii);

  Color black(0.f, 0.f, 0.f, 1.f);
  minGfxContext->SetColor(black);
  minGfxContext->SetPath(maskPath);
  minGfxContext->Fill();

  IntPoint topLeft;
  RefPtr<SourceSurface> minMask = DoBlur(minDrawTarget, &topLeft);
  if (!minMask) {
    return nullptr;
  }

  RefPtr<SourceSurface> minInsetBlur = CreateBoxShadow(minMask, aShadowColor);
  if (!minInsetBlur) {
    return nullptr;
  }

  IntRect blurRect(topLeft, minInsetBlur->GetSize());
  aExtendDestBy = blurRect - outerRect;

  if (useDestRect) {
    // Since we're just going to paint the actual rect to the destination
    aSlice.SizeTo(0, 0, 0, 0);
  } else {
    aSlice += aExtendDestBy;
    aSlice += aExtendDestBy;

    CacheInsetBlur(outerRect.Size(), innerRect.Size(),
                 aBlurRadius, aSpreadRadius,
                 &aInnerClipRadii, aShadowColor,
                 aHasBorderRadius, aDestDrawTarget->GetBackendType(),
                 aExtendDestBy, minInsetBlur);

  }

  return minInsetBlur.forget();
}