зеркало из https://github.com/mozilla/gecko-dev.git
Bug 880836. Add MaskSurface() to Azure. r=bas
This gives a substantial performance improvement over the more general Mask(): Test (MaskSurface10x10): 1.93042ms +/- 0.305028 Test (MaskSurface100x100): 2.33435ms +/- 1.00807 Test (MaskSurface500x500): 28.0472ms +/- 0.820744 Test (MaskSurface1000x1000): 107.656ms +/- 6.44615 Test (Mask10x10): 13.5237ms +/- 0.0932034 Test (Mask100x100): 14.0742ms +/- 1.21005 Test (Mask500x500): 96.5596ms +/- 1.81415 Test (Mask1000x1000): 356.891ms +/- 9.30592 --HG-- rename : layout/reftests/svg/text/dynamic-non-scaling-stroke-ref.svg => layout/reftests/svg/non-scaling-stroke-03-ref.svg rename : layout/reftests/svg/text/dynamic-non-scaling-stroke.svg => layout/reftests/svg/non-scaling-stroke-03.svg extra : rebase_source : a1218b8bc5cdcec7d4dd94561d841fb6e2a8ce5d
This commit is contained in:
Родитель
f810a607cb
Коммит
32dbe991d6
15
gfx/2d/2D.h
15
gfx/2d/2D.h
|
@ -706,6 +706,21 @@ public:
|
|||
const Pattern &aMask,
|
||||
const DrawOptions &aOptions = DrawOptions()) = 0;
|
||||
|
||||
/*
|
||||
* This takes a source pattern and a mask, and composites the source pattern
|
||||
* onto the destination surface using the alpha channel of the mask source.
|
||||
* The operation is bound by the extents of the mask.
|
||||
*
|
||||
* aSource Source pattern
|
||||
* aMask Mask surface
|
||||
* aOffset a transformed offset that the surface is masked at
|
||||
* aOptions Drawing options
|
||||
*/
|
||||
virtual void MaskSurface(const Pattern &aSource,
|
||||
SourceSurface *aMask,
|
||||
Point aOffset,
|
||||
const DrawOptions &aOptions = DrawOptions()) { MOZ_ASSERT(0); };
|
||||
|
||||
/*
|
||||
* Push a clip to the DrawTarget.
|
||||
*
|
||||
|
|
|
@ -300,6 +300,38 @@ DrawTargetCG::DrawSurface(SourceSurface *aSurface,
|
|||
CGImageRelease(subimage);
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetCG::MaskSurface(const Pattern &aSource,
|
||||
SourceSurface *aMask,
|
||||
Point aOffset,
|
||||
const DrawOptions &aDrawOptions)
|
||||
{
|
||||
MarkChanged();
|
||||
|
||||
CGImageRef image;
|
||||
CGContextSaveGState(mCg);
|
||||
|
||||
CGContextSetBlendMode(mCg, ToBlendMode(aDrawOptions.mCompositionOp));
|
||||
UnboundnessFixer fixer;
|
||||
CGContextRef cg = fixer.Check(mCg, aDrawOptions.mCompositionOp);
|
||||
CGContextSetAlpha(cg, aDrawOptions.mAlpha);
|
||||
|
||||
CGContextConcatCTM(cg, GfxMatrixToCGAffineTransform(mTransform));
|
||||
image = GetImageFromSourceSurface(aMask);
|
||||
|
||||
CGContextScaleCTM(cg, 1, -1);
|
||||
|
||||
IntSize size = aMask->GetSize();
|
||||
CGContextClipToMask(cg, CGRectMake(aOffset.x, aOffset.y, size.width, size.height), image);
|
||||
|
||||
FillRect(Rect(0, 0, size.width, size.height), aSource, aDrawOptions);
|
||||
|
||||
fixer.Fix(mCg);
|
||||
|
||||
CGContextRestoreGState(mCg);
|
||||
|
||||
}
|
||||
|
||||
static CGColorRef ColorToCGColor(CGColorSpaceRef aColorSpace, const Color& aColor)
|
||||
{
|
||||
CGFloat components[4] = {aColor.r, aColor.g, aColor.b, aColor.a};
|
||||
|
|
|
@ -96,6 +96,10 @@ public:
|
|||
const Rect &aSource,
|
||||
const DrawSurfaceOptions &aSurfOptions = DrawSurfaceOptions(),
|
||||
const DrawOptions &aOptions = DrawOptions());
|
||||
virtual void MaskSurface(const Pattern &aSource,
|
||||
SourceSurface *aMask,
|
||||
Point aOffset,
|
||||
const DrawOptions &aOptions = DrawOptions());
|
||||
|
||||
virtual void FillRect(const Rect &aRect,
|
||||
const Pattern &aPattern,
|
||||
|
|
|
@ -676,6 +676,55 @@ DrawTargetCairo::Mask(const Pattern &aSource,
|
|||
cairo_pattern_destroy(mask);
|
||||
cairo_pattern_destroy(source);
|
||||
}
|
||||
#if 0
|
||||
DrawTargetCairo::MaskSurface(SourceSurface *aSurface,
|
||||
const Rect &aDest,
|
||||
const Rect &aSource,
|
||||
const DrawSurfaceOptions &aSurfOptions,
|
||||
const DrawOptions &aOptions)
|
||||
{
|
||||
AutoPrepareForDrawing prep(this, mContext);
|
||||
|
||||
float sx = aSource.Width() / aDest.Width();
|
||||
float sy = aSource.Height() / aDest.Height();
|
||||
|
||||
cairo_matrix_t src_mat;
|
||||
cairo_matrix_init_translate(&src_mat, aSource.X(), aSource.Y());
|
||||
cairo_matrix_scale(&src_mat, sx, sy);
|
||||
|
||||
cairo_surface_t* surf = GetCairoSurfaceForSourceSurface(aSurface);
|
||||
cairo_pattern_t* pat = cairo_pattern_create_for_surface(surf);
|
||||
cairo_surface_destroy(surf);
|
||||
|
||||
cairo_pattern_set_matrix(pat, &src_mat);
|
||||
cairo_pattern_set_filter(pat, GfxFilterToCairoFilter(aSurfOptions.mFilter));
|
||||
cairo_pattern_set_extend(pat, CAIRO_EXTEND_PAD);
|
||||
|
||||
cairo_translate(mContext, aDest.X(), aDest.Y());
|
||||
|
||||
if (IsOperatorBoundByMask(aOptions.mCompositionOp)) {
|
||||
cairo_new_path(mContext);
|
||||
cairo_rectangle(mContext, 0, 0, aDest.Width(), aDest.Height());
|
||||
cairo_clip(mContext);
|
||||
cairo_set_source(mContext, pat);
|
||||
} else {
|
||||
cairo_push_group(mContext);
|
||||
cairo_new_path(mContext);
|
||||
cairo_rectangle(mContext, 0, 0, aDest.Width(), aDest.Height());
|
||||
cairo_set_source(mContext, pat);
|
||||
cairo_fill(mContext);
|
||||
cairo_pop_group_to_source(mContext);
|
||||
}
|
||||
|
||||
cairo_set_operator(mContext, GfxOpToCairoOp(aOptions.mCompositionOp));
|
||||
DrawPattern(aPattern, StrokeOptions(), aOptions, DRAW_FILL);
|
||||
|
||||
cairo_paint_with_alpha(mContext, aOptions.mAlpha);
|
||||
|
||||
cairo_pattern_destroy(pat);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
DrawTargetCairo::PushClip(const Path *aPath)
|
||||
|
|
|
@ -257,6 +257,63 @@ DrawTargetD2D::AddDependencyOnSource(SourceSurfaceD2DTarget* aSource)
|
|||
}
|
||||
}
|
||||
|
||||
TemporaryRef<ID2D1Bitmap>
|
||||
DrawTargetD2D::GetBitmapForSurface(SourceSurface *aSurface,
|
||||
Rect &aSource)
|
||||
{
|
||||
RefPtr<ID2D1Bitmap> bitmap;
|
||||
|
||||
switch (aSurface->GetType()) {
|
||||
|
||||
case SURFACE_D2D1_BITMAP:
|
||||
{
|
||||
SourceSurfaceD2D *srcSurf = static_cast<SourceSurfaceD2D*>(aSurface);
|
||||
bitmap = srcSurf->GetBitmap();
|
||||
}
|
||||
break;
|
||||
case SURFACE_D2D1_DRAWTARGET:
|
||||
{
|
||||
SourceSurfaceD2DTarget *srcSurf = static_cast<SourceSurfaceD2DTarget*>(aSurface);
|
||||
bitmap = srcSurf->GetBitmap(mRT);
|
||||
AddDependencyOnSource(srcSurf);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
RefPtr<DataSourceSurface> srcSurf = aSurface->GetDataSurface();
|
||||
|
||||
if (!srcSurf) {
|
||||
gfxDebug() << "Not able to deal with non-data source surface.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (aSource.width > mRT->GetMaximumBitmapSize() ||
|
||||
aSource.height > mRT->GetMaximumBitmapSize()) {
|
||||
gfxDebug() << "Bitmap source larger than texture size specified. DrawBitmap will silently fail.";
|
||||
// Don't know how to deal with this yet.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int stride = srcSurf->Stride();
|
||||
|
||||
unsigned char *data = srcSurf->GetData() +
|
||||
(uint32_t)aSource.y * stride +
|
||||
(uint32_t)aSource.x * BytesPerPixel(srcSurf->GetFormat());
|
||||
|
||||
D2D1_BITMAP_PROPERTIES props =
|
||||
D2D1::BitmapProperties(D2D1::PixelFormat(DXGIFormat(srcSurf->GetFormat()), AlphaMode(srcSurf->GetFormat())));
|
||||
mRT->CreateBitmap(D2D1::SizeU(UINT32(aSource.width), UINT32(aSource.height)), data, stride, props, byRef(bitmap));
|
||||
|
||||
// subtract the integer part leaving the fractional part
|
||||
aSource.x -= (uint32_t)aSource.x;
|
||||
aSource.y -= (uint32_t)aSource.y;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetD2D::DrawSurface(SourceSurface *aSurface,
|
||||
const Rect &aDest,
|
||||
|
@ -274,62 +331,45 @@ DrawTargetD2D::DrawSurface(SourceSurface *aSurface,
|
|||
|
||||
Rect srcRect = aSource;
|
||||
|
||||
switch (aSurface->GetType()) {
|
||||
|
||||
case SURFACE_D2D1_BITMAP:
|
||||
{
|
||||
SourceSurfaceD2D *srcSurf = static_cast<SourceSurfaceD2D*>(aSurface);
|
||||
bitmap = srcSurf->GetBitmap();
|
||||
|
||||
if (!bitmap) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SURFACE_D2D1_DRAWTARGET:
|
||||
{
|
||||
SourceSurfaceD2DTarget *srcSurf = static_cast<SourceSurfaceD2DTarget*>(aSurface);
|
||||
bitmap = srcSurf->GetBitmap(mRT);
|
||||
AddDependencyOnSource(srcSurf);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
RefPtr<DataSourceSurface> srcSurf = aSurface->GetDataSurface();
|
||||
|
||||
if (!srcSurf) {
|
||||
gfxDebug() << "Not able to deal with non-data source surface.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (aSource.width > rt->GetMaximumBitmapSize() ||
|
||||
aSource.height > rt->GetMaximumBitmapSize()) {
|
||||
gfxDebug() << "Bitmap source larger than texture size specified. DrawBitmap will silently fail.";
|
||||
// Don't know how to deal with this yet.
|
||||
return;
|
||||
}
|
||||
|
||||
int stride = srcSurf->Stride();
|
||||
|
||||
unsigned char *data = srcSurf->GetData() +
|
||||
(uint32_t)aSource.y * stride +
|
||||
(uint32_t)aSource.x * BytesPerPixel(srcSurf->GetFormat());
|
||||
|
||||
D2D1_BITMAP_PROPERTIES props =
|
||||
D2D1::BitmapProperties(D2D1::PixelFormat(DXGIFormat(srcSurf->GetFormat()), AlphaMode(srcSurf->GetFormat())));
|
||||
mRT->CreateBitmap(D2D1::SizeU(UINT32(aSource.width), UINT32(aSource.height)), data, stride, props, byRef(bitmap));
|
||||
|
||||
srcRect.x -= (uint32_t)aSource.x;
|
||||
srcRect.y -= (uint32_t)aSource.y;
|
||||
}
|
||||
break;
|
||||
bitmap = GetBitmapForSurface(aSurface, srcRect);
|
||||
if (!bitmap) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
rt->DrawBitmap(bitmap, D2DRect(aDest), aOptions.mAlpha, D2DFilter(aSurfOptions.mFilter), D2DRect(srcRect));
|
||||
|
||||
FinalizeRTForOperation(aOptions.mCompositionOp, ColorPattern(Color()), aDest);
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetD2D::MaskSurface(const Pattern &aSource,
|
||||
SourceSurface *aMask,
|
||||
Point aOffset,
|
||||
const DrawOptions &aOptions)
|
||||
{
|
||||
RefPtr<ID2D1Bitmap> bitmap;
|
||||
|
||||
ID2D1RenderTarget *rt = GetRTForOperation(aOptions.mCompositionOp, ColorPattern(Color()));
|
||||
|
||||
PrepareForDrawing(rt);
|
||||
|
||||
// FillOpacityMask only works if the antialias mode is MODE_ALIASED
|
||||
rt->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
|
||||
|
||||
IntSize size = aMask->GetSize();
|
||||
Rect maskRect = Rect(0.f, 0.f, size.width, size.height);
|
||||
bitmap = GetBitmapForSurface(aMask, maskRect);
|
||||
if (!bitmap) {
|
||||
return;
|
||||
}
|
||||
|
||||
Rect dest = Rect(aOffset.x, aOffset.y, size.width, size.height);
|
||||
RefPtr<ID2D1Brush> brush = CreateBrushForPattern(aSource, aOptions.mAlpha);
|
||||
rt->FillOpacityMask(bitmap, brush, D2D1_OPACITY_MASK_CONTENT_GRAPHICS, D2DRect(dest), D2DRect(maskRect));
|
||||
|
||||
FinalizeRTForOperation(aOptions.mCompositionOp, ColorPattern(Color()), dest);
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetD2D::DrawSurfaceWithShadow(SourceSurface *aSurface,
|
||||
const Point &aDest,
|
||||
|
|
|
@ -63,6 +63,11 @@ public:
|
|||
Float aSigma,
|
||||
CompositionOp aOperator);
|
||||
virtual void ClearRect(const Rect &aRect);
|
||||
virtual void MaskSurface(const Pattern &aSource,
|
||||
SourceSurface *aMask,
|
||||
Point aOffset,
|
||||
const DrawOptions &aOptions = DrawOptions());
|
||||
|
||||
|
||||
virtual void CopySurface(SourceSurface *aSurface,
|
||||
const IntRect &aSourceRect,
|
||||
|
@ -142,6 +147,9 @@ public:
|
|||
static uint64_t mVRAMUsageSS;
|
||||
|
||||
private:
|
||||
TemporaryRef<ID2D1Bitmap>
|
||||
DrawTargetD2D::GetBitmapForSurface(SourceSurface *aSurface,
|
||||
Rect &aSource);
|
||||
friend class AutoSaveRestoreClippedOut;
|
||||
friend class SourceSurfaceD2DTarget;
|
||||
|
||||
|
|
|
@ -1397,7 +1397,6 @@ gfxContext::GetPattern()
|
|||
|
||||
|
||||
// masking
|
||||
|
||||
void
|
||||
gfxContext::Mask(gfxPattern *pattern)
|
||||
{
|
||||
|
@ -1463,12 +1462,10 @@ gfxContext::Mask(gfxASurface *surface, const gfxPoint& offset)
|
|||
gfxPoint pt = surface->GetDeviceOffset();
|
||||
|
||||
// We clip here to bind to the mask surface bounds, see above.
|
||||
mDT->PushClipRect(Rect(offset.x - pt.x, offset.y - pt.y, sourceSurf->GetSize().width, sourceSurf->GetSize().height));
|
||||
mDT->Mask(GeneralPattern(this),
|
||||
SurfacePattern(sourceSurf, EXTEND_CLAMP,
|
||||
Matrix(1.0f, 0, 0, 1.0f, Float(offset.x - pt.x), Float(offset.y - pt.y))),
|
||||
mDT->MaskSurface(GeneralPattern(this),
|
||||
sourceSurf,
|
||||
Point(offset.x - pt.x, offset.y - pt.y),
|
||||
DrawOptions(1.0f, CurrentState().op, CurrentState().aaMode));
|
||||
mDT->PopClip();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1716,7 +1716,7 @@ skip-if(B2G) == 751012-1b.html 751012-1-ref.html
|
|||
random-if(Android) == 753329-1.html about:blank
|
||||
== 758561-1.html 758561-1-ref.html
|
||||
fuzzy-if(true,1,19) fails-if(d2d) == 759036-1.html 759036-1-ref.html
|
||||
fuzzy-if(true,17,5859) == 759036-2.html 759036-2-ref.html
|
||||
fuzzy-if(true,17,5860) == 759036-2.html 759036-2-ref.html
|
||||
== 776265-1a.html 776265-1-ref.html
|
||||
== 776265-1b.html 776265-1-ref.html
|
||||
== 776265-1c.html 776265-1-ref.html
|
||||
|
|
Загрузка…
Ссылка в новой задаче