mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 12:51:06 +00:00
Bug 1439005. Add PushLayerWithBlend. r=Bas
This makes it possible to implement nsDisplayBlend blob image invalidation. It currently only includes an implementation for Skia and DrawTargetRecording. All other backends will crash when used. MozReview-Commit-ID: 2GhdDxi4jHG
This commit is contained in:
parent
d70a10cbd8
commit
62a9686ee2
24
gfx/2d/2D.h
24
gfx/2d/2D.h
@ -1222,6 +1222,30 @@ public:
|
||||
const IntRect& aBounds = IntRect(),
|
||||
bool aCopyBackground = false) { MOZ_CRASH("GFX: PushLayer"); }
|
||||
|
||||
/**
|
||||
* Push a 'layer' to the DrawTarget, a layer is a temporary surface that all
|
||||
* drawing will be redirected to, this is used for example to support group
|
||||
* opacity or the masking of groups. Clips must be balanced within a layer,
|
||||
* i.e. between a matching PushLayer/PopLayer pair there must be as many
|
||||
* PushClip(Rect) calls as there are PopClip calls.
|
||||
*
|
||||
* @param aOpaque Whether the layer will be opaque
|
||||
* @param aOpacity Opacity of the layer
|
||||
* @param aMask Mask applied to the layer
|
||||
* @param aMaskTransform Transform applied to the layer mask
|
||||
* @param aBounds Optional bounds in device space to which the layer is
|
||||
* limited in size.
|
||||
* @param aCopyBackground Whether to copy the background into the layer, this
|
||||
* is only supported when aOpaque is true.
|
||||
*/
|
||||
virtual void PushLayerWithBlend(bool aOpaque, Float aOpacity,
|
||||
SourceSurface* aMask,
|
||||
const Matrix& aMaskTransform,
|
||||
const IntRect& aBounds = IntRect(),
|
||||
bool aCopyBackground = false,
|
||||
CompositionOp = CompositionOp::OP_OVER) { MOZ_CRASH("GFX: PushLayerWithBlend"); }
|
||||
|
||||
|
||||
/**
|
||||
* This balances a call to PushLayer and proceeds to blend the layer back
|
||||
* onto the background. This blend will blend the temporary surface back
|
||||
|
@ -526,6 +526,23 @@ DrawTargetRecording::PushLayer(bool aOpaque, Float aOpacity,
|
||||
aCopyBackground));
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetRecording::PushLayerWithBlend(bool aOpaque, Float aOpacity,
|
||||
SourceSurface* aMask,
|
||||
const Matrix& aMaskTransform,
|
||||
const IntRect& aBounds,
|
||||
bool aCopyBackground,
|
||||
CompositionOp aCompositionOp)
|
||||
{
|
||||
if (aMask) {
|
||||
EnsureSurfaceStoredRecording(mRecorder, aMask, "PushLayer");
|
||||
}
|
||||
|
||||
mRecorder->RecordEvent(RecordedPushLayerWithBlend(this, aOpaque, aOpacity, aMask,
|
||||
aMaskTransform, aBounds,
|
||||
aCopyBackground, aCompositionOp));
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetRecording::PopLayer()
|
||||
{
|
||||
|
@ -231,6 +231,32 @@ public:
|
||||
const IntRect& aBounds = IntRect(),
|
||||
bool aCopyBackground = false) override;
|
||||
|
||||
/**
|
||||
* Push a 'layer' to the DrawTarget, a layer is a temporary surface that all
|
||||
* drawing will be redirected to, this is used for example to support group
|
||||
* opacity or the masking of groups. Clips must be balanced within a layer,
|
||||
* i.e. between a matching PushLayer/PopLayer pair there must be as many
|
||||
* PushClip(Rect) calls as there are PopClip calls.
|
||||
*
|
||||
* @param aOpaque Whether the layer will be opaque
|
||||
* @param aOpacity Opacity of the layer
|
||||
* @param aMask Mask applied to the layer
|
||||
* @param aMaskTransform Transform applied to the layer mask
|
||||
* @param aBounds Optional bounds in device space to which the layer is
|
||||
* limited in size.
|
||||
* @param aCopyBackground Whether to copy the background into the layer, this
|
||||
* is only supported when aOpaque is true.a
|
||||
* @param aCompositionOp The CompositionOp to use when blending the layer into
|
||||
* the destination
|
||||
*/
|
||||
virtual void PushLayerWithBlend(bool aOpaque, Float aOpacity,
|
||||
SourceSurface* aMask,
|
||||
const Matrix& aMaskTransform,
|
||||
const IntRect& aBounds = IntRect(),
|
||||
bool aCopyBackground = false,
|
||||
CompositionOp aCompositionOp = CompositionOp::OP_OVER) override;
|
||||
|
||||
|
||||
/**
|
||||
* This balances a call to PushLayer and proceeds to blend the layer back
|
||||
* onto the background. This blend will blend the temporary surface back
|
||||
|
@ -2067,7 +2067,15 @@ DrawTargetSkia::PushLayer(bool aOpaque, Float aOpacity, SourceSurface* aMask,
|
||||
const Matrix& aMaskTransform, const IntRect& aBounds,
|
||||
bool aCopyBackground)
|
||||
{
|
||||
PushedLayer layer(GetPermitSubpixelAA(), aOpaque, aOpacity, aMask, aMaskTransform,
|
||||
PushLayerWithBlend(aOpaque, aOpacity, aMask, aMaskTransform, aBounds, aCopyBackground, CompositionOp::OP_OVER);
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetSkia::PushLayerWithBlend(bool aOpaque, Float aOpacity, SourceSurface* aMask,
|
||||
const Matrix& aMaskTransform, const IntRect& aBounds,
|
||||
bool aCopyBackground, CompositionOp aCompositionOp)
|
||||
{
|
||||
PushedLayer layer(GetPermitSubpixelAA(), aOpaque, aOpacity, aCompositionOp, aMask, aMaskTransform,
|
||||
mCanvas->getTopDevice());
|
||||
mPushedLayers.push_back(layer);
|
||||
|
||||
@ -2076,6 +2084,9 @@ DrawTargetSkia::PushLayer(bool aOpaque, Float aOpacity, SourceSurface* aMask,
|
||||
// If we have a mask, set the opacity to 0 so that SkCanvas::restore skips
|
||||
// implicitly drawing the layer so that we can properly mask it in PopLayer.
|
||||
paint.setAlpha(aMask ? 0 : ColorFloatToByte(aOpacity));
|
||||
if (!aMask) {
|
||||
paint.setBlendMode(GfxOpToSkiaOp(layer.mCompositionOp));
|
||||
}
|
||||
|
||||
// aBounds is supplied in device space, but SaveLayerRec wants local space.
|
||||
SkRect bounds = IntRectToSkRect(aBounds);
|
||||
@ -2142,6 +2153,7 @@ DrawTargetSkia::PopLayer()
|
||||
|
||||
SkPaint paint;
|
||||
paint.setAlpha(ColorFloatToByte(layer.mOpacity));
|
||||
paint.setBlendMode(GfxOpToSkiaOp(layer.mCompositionOp));
|
||||
|
||||
SkMatrix maskMat, layerMat;
|
||||
// Get the total transform affecting the mask, considering its pattern
|
||||
|
@ -109,6 +109,12 @@ public:
|
||||
const Matrix& aMaskTransform,
|
||||
const IntRect& aBounds = IntRect(),
|
||||
bool aCopyBackground = false) override;
|
||||
virtual void PushLayerWithBlend(bool aOpaque, Float aOpacity,
|
||||
SourceSurface* aMask,
|
||||
const Matrix& aMaskTransform,
|
||||
const IntRect& aBounds = IntRect(),
|
||||
bool aCopyBackground = false,
|
||||
CompositionOp aCompositionOp = CompositionOp::OP_OVER) override;
|
||||
virtual void PopLayer() override;
|
||||
virtual void Blur(const AlphaBoxBlur& aBlur) override;
|
||||
virtual already_AddRefed<SourceSurface> CreateSourceSurfaceFromData(unsigned char *aData,
|
||||
@ -178,12 +184,14 @@ private:
|
||||
PushedLayer(bool aOldPermitSubpixelAA,
|
||||
bool aOpaque,
|
||||
Float aOpacity,
|
||||
CompositionOp aCompositionOp,
|
||||
SourceSurface* aMask,
|
||||
const Matrix& aMaskTransform,
|
||||
SkBaseDevice* aPreviousDevice)
|
||||
: mOldPermitSubpixelAA(aOldPermitSubpixelAA),
|
||||
mOpaque(aOpaque),
|
||||
mOpacity(aOpacity),
|
||||
mCompositionOp(aCompositionOp),
|
||||
mMask(aMask),
|
||||
mMaskTransform(aMaskTransform),
|
||||
mPreviousDevice(aPreviousDevice)
|
||||
@ -191,6 +199,7 @@ private:
|
||||
bool mOldPermitSubpixelAA;
|
||||
bool mOpaque;
|
||||
Float mOpacity;
|
||||
CompositionOp mCompositionOp;
|
||||
RefPtr<SourceSurface> mMask;
|
||||
Matrix mMaskTransform;
|
||||
SkBaseDevice* mPreviousDevice;
|
||||
|
@ -256,6 +256,7 @@ public:
|
||||
FONTDATA,
|
||||
FONTDESC,
|
||||
PUSHLAYER,
|
||||
PUSHLAYERWITHBLEND,
|
||||
POPLAYER,
|
||||
UNSCALEDFONTCREATION,
|
||||
UNSCALEDFONTDESTRUCTION,
|
||||
|
@ -530,6 +530,42 @@ private:
|
||||
bool mCopyBackground;
|
||||
};
|
||||
|
||||
class RecordedPushLayerWithBlend : public RecordedDrawingEvent<RecordedPushLayerWithBlend> {
|
||||
public:
|
||||
RecordedPushLayerWithBlend(DrawTarget* aDT, bool aOpaque, Float aOpacity,
|
||||
SourceSurface* aMask, const Matrix& aMaskTransform,
|
||||
const IntRect& aBounds, bool aCopyBackground,
|
||||
CompositionOp aCompositionOp)
|
||||
: RecordedDrawingEvent(PUSHLAYERWITHBLEND, aDT), mOpaque(aOpaque)
|
||||
, mOpacity(aOpacity), mMask(aMask), mMaskTransform(aMaskTransform)
|
||||
, mBounds(aBounds), mCopyBackground(aCopyBackground)
|
||||
, mCompositionOp(aCompositionOp)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool PlayEvent(Translator *aTranslator) const override;
|
||||
|
||||
template<class S> void Record(S &aStream) const;
|
||||
virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const override;
|
||||
|
||||
virtual std::string GetName() const override { return "PushLayerWithBlend"; }
|
||||
|
||||
private:
|
||||
friend class RecordedEvent;
|
||||
|
||||
template<class S>
|
||||
MOZ_IMPLICIT RecordedPushLayerWithBlend(S &aStream);
|
||||
|
||||
bool mOpaque;
|
||||
Float mOpacity;
|
||||
ReferencePtr mMask;
|
||||
Matrix mMaskTransform;
|
||||
IntRect mBounds;
|
||||
bool mCopyBackground;
|
||||
CompositionOp mCompositionOp;
|
||||
};
|
||||
|
||||
|
||||
class RecordedPopLayer : public RecordedDrawingEvent<RecordedPopLayer> {
|
||||
public:
|
||||
MOZ_IMPLICIT RecordedPopLayer(DrawTarget* aDT)
|
||||
@ -2267,6 +2303,51 @@ RecordedPushLayer::OutputSimpleEventInfo(std::stringstream &aStringStream) const
|
||||
", Opacity=" << mOpacity << ", Mask Ref=" << mMask << ") ";
|
||||
}
|
||||
|
||||
inline bool
|
||||
RecordedPushLayerWithBlend::PlayEvent(Translator *aTranslator) const
|
||||
{
|
||||
SourceSurface* mask = mMask ? aTranslator->LookupSourceSurface(mMask)
|
||||
: nullptr;
|
||||
aTranslator->LookupDrawTarget(mDT)->
|
||||
PushLayerWithBlend(mOpaque, mOpacity, mask, mMaskTransform, mBounds, mCopyBackground, mCompositionOp);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class S>
|
||||
void
|
||||
RecordedPushLayerWithBlend::Record(S &aStream) const
|
||||
{
|
||||
RecordedDrawingEvent::Record(aStream);
|
||||
WriteElement(aStream, mOpaque);
|
||||
WriteElement(aStream, mOpacity);
|
||||
WriteElement(aStream, mMask);
|
||||
WriteElement(aStream, mMaskTransform);
|
||||
WriteElement(aStream, mBounds);
|
||||
WriteElement(aStream, mCopyBackground);
|
||||
WriteElement(aStream, mCompositionOp);
|
||||
}
|
||||
|
||||
template<class S>
|
||||
RecordedPushLayerWithBlend::RecordedPushLayerWithBlend(S &aStream)
|
||||
: RecordedDrawingEvent(PUSHLAYERWITHBLEND, aStream)
|
||||
{
|
||||
ReadElement(aStream, mOpaque);
|
||||
ReadElement(aStream, mOpacity);
|
||||
ReadElement(aStream, mMask);
|
||||
ReadElement(aStream, mMaskTransform);
|
||||
ReadElement(aStream, mBounds);
|
||||
ReadElement(aStream, mCopyBackground);
|
||||
ReadElement(aStream, mCompositionOp);
|
||||
}
|
||||
|
||||
inline void
|
||||
RecordedPushLayerWithBlend::OutputSimpleEventInfo(std::stringstream &aStringStream) const
|
||||
{
|
||||
aStringStream << "[" << mDT << "] PushLayerWithBlend (Opaque=" << mOpaque <<
|
||||
", Opacity=" << mOpacity << ", Mask Ref=" << mMask << ") ";
|
||||
}
|
||||
|
||||
|
||||
inline bool
|
||||
RecordedPopLayer::PlayEvent(Translator *aTranslator) const
|
||||
{
|
||||
@ -3411,6 +3492,7 @@ RecordedFilterNodeSetInput::OutputSimpleEventInfo(std::stringstream &aStringStre
|
||||
f(FONTDATA, RecordedFontData); \
|
||||
f(FONTDESC, RecordedFontDescriptor); \
|
||||
f(PUSHLAYER, RecordedPushLayer); \
|
||||
f(PUSHLAYERWITHBLEND, RecordedPushLayerWithBlend); \
|
||||
f(POPLAYER, RecordedPopLayer); \
|
||||
f(UNSCALEDFONTCREATION, RecordedUnscaledFontCreation); \
|
||||
f(UNSCALEDFONTDESTRUCTION, RecordedUnscaledFontDestruction); \
|
||||
|
Loading…
Reference in New Issue
Block a user