mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 983574 - When setting a SourceSurface input on a FilterNodeD2D1, delay the conversion to ID2D1Image until the actual DrawFilter call. r=Bas
This commit is contained in:
parent
de564f5251
commit
e02b56d697
@ -388,7 +388,10 @@ DrawTargetD2D::DrawFilter(FilterNode *aNode,
|
||||
hr = rt->QueryInterface((ID2D1DeviceContext**)byRef(dc));
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
dc->DrawImage(static_cast<FilterNodeD2D1*>(aNode)->OutputEffect(), D2DPoint(aDestPoint), D2DRect(aSourceRect));
|
||||
FilterNodeD2D1* node = static_cast<FilterNodeD2D1*>(aNode);
|
||||
node->WillDraw(this);
|
||||
|
||||
dc->DrawImage(node->OutputEffect(), D2DPoint(aDestPoint), D2DRect(aSourceRect));
|
||||
|
||||
Rect destRect = aSourceRect;
|
||||
destRect.MoveBy(aDestPoint);
|
||||
@ -1320,7 +1323,7 @@ DrawTargetD2D::CreateFilter(FilterType aType)
|
||||
HRESULT hr = mRT->QueryInterface((ID2D1DeviceContext**)byRef(dc));
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
return FilterNodeD2D1::Create(this, dc, aType);
|
||||
return FilterNodeD2D1::Create(dc, aType);
|
||||
}
|
||||
#endif
|
||||
return FilterNodeSoftware::Create(aType);
|
||||
|
@ -155,7 +155,10 @@ DrawTargetD2D1::DrawFilter(FilterNode *aNode,
|
||||
|
||||
mDC->SetAntialiasMode(D2DAAMode(aOptions.mAntialiasMode));
|
||||
|
||||
mDC->DrawImage(static_cast<FilterNodeD2D1*>(aNode)->OutputEffect(), D2DPoint(aDestPoint), D2DRect(aSourceRect));
|
||||
FilterNodeD2D1* node = static_cast<FilterNodeD2D1*>(aNode);
|
||||
node->WillDraw(this);
|
||||
|
||||
mDC->DrawImage(node->OutputEffect(), D2DPoint(aDestPoint), D2DRect(aSourceRect));
|
||||
|
||||
FinalizeDrawing(aOptions.mCompositionOp, ColorPattern(Color()));
|
||||
}
|
||||
@ -701,7 +704,7 @@ DrawTargetD2D1::CreateGradientStops(GradientStop *rawStops, uint32_t aNumStops,
|
||||
TemporaryRef<FilterNode>
|
||||
DrawTargetD2D1::CreateFilter(FilterType aType)
|
||||
{
|
||||
return FilterNodeD2D1::Create(this, mDC, aType);
|
||||
return FilterNodeD2D1::Create(mDC, aType);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -523,10 +523,10 @@ static inline REFCLSID GetCLDIDForFilterType(FilterType aType)
|
||||
|
||||
/* static */
|
||||
TemporaryRef<FilterNode>
|
||||
FilterNodeD2D1::Create(DrawTarget* aDT, ID2D1DeviceContext *aDC, FilterType aType)
|
||||
FilterNodeD2D1::Create(ID2D1DeviceContext *aDC, FilterType aType)
|
||||
{
|
||||
if (aType == FilterType::CONVOLVE_MATRIX) {
|
||||
return new FilterNodeConvolveD2D1(aDT, aDC);
|
||||
return new FilterNodeConvolveD2D1(aDC);
|
||||
}
|
||||
|
||||
RefPtr<ID2D1Effect> effect;
|
||||
@ -544,9 +544,9 @@ FilterNodeD2D1::Create(DrawTarget* aDT, ID2D1DeviceContext *aDC, FilterType aTyp
|
||||
case FilterType::GAMMA_TRANSFER:
|
||||
case FilterType::TABLE_TRANSFER:
|
||||
case FilterType::DISCRETE_TRANSFER:
|
||||
return new FilterNodeComponentTransferD2D1(aDT, aDC, effect, aType);
|
||||
return new FilterNodeComponentTransferD2D1(aDC, effect, aType);
|
||||
default:
|
||||
return new FilterNodeD2D1(aDT, effect, aType);
|
||||
return new FilterNodeD2D1(effect, aType);
|
||||
}
|
||||
}
|
||||
|
||||
@ -579,8 +579,23 @@ FilterNodeD2D1::SetInput(uint32_t aIndex, SourceSurface *aSurface)
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr<ID2D1Image> image = GetImageForSourceSurface(mDT, aSurface);
|
||||
effect->SetInput(input, image);
|
||||
MOZ_ASSERT(input < effect->GetInputCount());
|
||||
|
||||
mInputSurfaces.resize(effect->GetInputCount());
|
||||
mInputFilters.resize(effect->GetInputCount());
|
||||
|
||||
// In order to convert aSurface into an ID2D1Image, we need to know what
|
||||
// DrawTarget we paint into. However, the same FilterNode object can be
|
||||
// used on different DrawTargets, so we need to hold on to the SourceSurface
|
||||
// objects and delay the conversion until we're actually painted and know
|
||||
// our target DrawTarget.
|
||||
// The conversion happens in WillDraw().
|
||||
|
||||
mInputSurfaces[input] = aSurface;
|
||||
mInputFilters[input] = nullptr;
|
||||
|
||||
// Clear the existing image from the effect.
|
||||
effect->SetInput(input, nullptr);
|
||||
}
|
||||
|
||||
void
|
||||
@ -599,15 +614,47 @@ FilterNodeD2D1::SetInput(uint32_t aIndex, FilterNode *aFilter)
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_ASSERT(input < effect->GetInputCount());
|
||||
MOZ_ASSERT(input < effect->GetInputCount());
|
||||
|
||||
if (aFilter->GetBackendType() != FILTER_BACKEND_DIRECT2D1_1) {
|
||||
gfxWarning() << "Unknown input SourceSurface set on effect.";
|
||||
if (aFilter && aFilter->GetBackendType() != FILTER_BACKEND_DIRECT2D1_1) {
|
||||
gfxWarning() << "Unknown input FilterNode set on effect.";
|
||||
MOZ_ASSERT(0);
|
||||
return;
|
||||
}
|
||||
|
||||
effect->SetInputEffect(input, static_cast<FilterNodeD2D1*>(aFilter)->OutputEffect());
|
||||
FilterNodeD2D1* filter = static_cast<FilterNodeD2D1*>(aFilter);
|
||||
|
||||
mInputSurfaces.resize(effect->GetInputCount());
|
||||
mInputFilters.resize(effect->GetInputCount());
|
||||
|
||||
// We hold on to the FilterNode object so that we can call WillDraw() on it.
|
||||
mInputSurfaces[input] = nullptr;
|
||||
mInputFilters[input] = filter;
|
||||
|
||||
if (filter) {
|
||||
effect->SetInputEffect(input, filter->OutputEffect());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FilterNodeD2D1::WillDraw(DrawTarget *aDT)
|
||||
{
|
||||
// Convert input SourceSurfaces into ID2D1Images and set them on the effect.
|
||||
for (size_t inputIndex = 0; inputIndex < mInputSurfaces.size(); inputIndex++) {
|
||||
if (mInputSurfaces[inputIndex]) {
|
||||
ID2D1Effect* effect = InputEffect();
|
||||
RefPtr<ID2D1Image> image = GetImageForSourceSurface(aDT, mInputSurfaces[inputIndex]);
|
||||
effect->SetInput(inputIndex, image);
|
||||
}
|
||||
}
|
||||
|
||||
// Call WillDraw() on our input filters.
|
||||
for (std::vector<RefPtr<FilterNodeD2D1>>::iterator it = mInputFilters.begin();
|
||||
it != mInputFilters.end(); it++) {
|
||||
if (*it) {
|
||||
(*it)->WillDraw(aDT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -771,8 +818,8 @@ FilterNodeD2D1::SetAttribute(uint32_t aIndex, const Matrix &aMatrix)
|
||||
mEffect->SetValue(input, D2DMatrix(aMatrix));
|
||||
}
|
||||
|
||||
FilterNodeConvolveD2D1::FilterNodeConvolveD2D1(DrawTarget *aDT, ID2D1DeviceContext *aDC)
|
||||
: FilterNodeD2D1(aDT, nullptr, FilterType::CONVOLVE_MATRIX)
|
||||
FilterNodeConvolveD2D1::FilterNodeConvolveD2D1(ID2D1DeviceContext *aDC)
|
||||
: FilterNodeD2D1(nullptr, FilterType::CONVOLVE_MATRIX)
|
||||
, mEdgeMode(EDGE_MODE_DUPLICATE)
|
||||
{
|
||||
// Correctly handling the interaction of edge mode and source rect is a bit
|
||||
@ -845,31 +892,10 @@ FilterNodeConvolveD2D1::FilterNodeConvolveD2D1(DrawTarget *aDT, ID2D1DeviceConte
|
||||
UpdateSourceRect();
|
||||
}
|
||||
|
||||
void
|
||||
FilterNodeConvolveD2D1::SetInput(uint32_t aIndex, SourceSurface *aSurface)
|
||||
{
|
||||
MOZ_ASSERT(aIndex == 0);
|
||||
|
||||
mInput = GetImageForSourceSurface(mDT, aSurface);
|
||||
|
||||
mInputEffect = nullptr;
|
||||
|
||||
UpdateChain();
|
||||
}
|
||||
|
||||
void
|
||||
FilterNodeConvolveD2D1::SetInput(uint32_t aIndex, FilterNode *aFilter)
|
||||
{
|
||||
MOZ_ASSERT(aIndex == 0);
|
||||
|
||||
if (aFilter->GetBackendType() != FILTER_BACKEND_DIRECT2D1_1) {
|
||||
gfxWarning() << "Unknown input SourceSurface set on effect.";
|
||||
MOZ_ASSERT(0);
|
||||
return;
|
||||
}
|
||||
|
||||
mInput = nullptr;
|
||||
mInputEffect = static_cast<FilterNodeD2D1*>(aFilter)->mEffect;
|
||||
FilterNodeD2D1::SetInput(aIndex, aFilter);
|
||||
|
||||
UpdateChain();
|
||||
}
|
||||
@ -886,6 +912,12 @@ FilterNodeConvolveD2D1::SetAttribute(uint32_t aIndex, uint32_t aValue)
|
||||
UpdateChain();
|
||||
}
|
||||
|
||||
ID2D1Effect*
|
||||
FilterNodeConvolveD2D1::InputEffect()
|
||||
{
|
||||
return mEdgeMode == EDGE_MODE_NONE ? mEffect.get() : mCompositeEffect.get();
|
||||
}
|
||||
|
||||
void
|
||||
FilterNodeConvolveD2D1::UpdateChain()
|
||||
{
|
||||
@ -897,19 +929,18 @@ FilterNodeConvolveD2D1::UpdateChain()
|
||||
// EDGE_MODE_DUPLICATE or EDGE_MODE_WRAP:
|
||||
// input -------v
|
||||
// flood --> composite --> crop --> border --> convolvematrix
|
||||
//
|
||||
// mEffect is convolvematrix.
|
||||
|
||||
ID2D1Effect *firstEffect = mCompositeEffect;
|
||||
if (mEdgeMode == EDGE_MODE_NONE) {
|
||||
firstEffect = mEffect;
|
||||
} else {
|
||||
if (mEdgeMode != EDGE_MODE_NONE) {
|
||||
mEffect->SetInputEffect(0, mBorderEffect.get());
|
||||
}
|
||||
|
||||
if (mInputEffect) {
|
||||
firstEffect->SetInputEffect(0, mInputEffect);
|
||||
} else {
|
||||
firstEffect->SetInput(0, mInput);
|
||||
RefPtr<ID2D1Effect> inputEffect;
|
||||
if (mInputFilters.size() > 0 && mInputFilters[0]) {
|
||||
inputEffect = mInputFilters[0]->OutputEffect();
|
||||
}
|
||||
InputEffect()->SetInputEffect(0, inputEffect);
|
||||
|
||||
if (mEdgeMode == EDGE_MODE_DUPLICATE) {
|
||||
mBorderEffect->SetValue(D2D1_BORDER_PROP_EDGE_MODE_X, D2D1_BORDER_EDGE_MODE_CLAMP);
|
||||
@ -980,9 +1011,9 @@ FilterNodeConvolveD2D1::UpdateSourceRect()
|
||||
Float(mSourceRect.XMost()), Float(mSourceRect.YMost())));
|
||||
}
|
||||
|
||||
FilterNodeComponentTransferD2D1::FilterNodeComponentTransferD2D1(DrawTarget *aDT, ID2D1DeviceContext *aDC,
|
||||
FilterNodeComponentTransferD2D1::FilterNodeComponentTransferD2D1(ID2D1DeviceContext *aDC,
|
||||
ID2D1Effect *aEffect, FilterType aType)
|
||||
: FilterNodeD2D1(aDT, aEffect, aType)
|
||||
: FilterNodeD2D1(aEffect, aType)
|
||||
{
|
||||
// D2D1 component transfer effects do strange things when it comes to
|
||||
// premultiplication.
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include "2D.h"
|
||||
#include "Filters.h"
|
||||
#include <vector>
|
||||
#include <d2d1_1.h>
|
||||
#include <cguid.h>
|
||||
|
||||
@ -18,11 +19,10 @@ class FilterNodeD2D1 : public FilterNode
|
||||
{
|
||||
public:
|
||||
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeD2D1)
|
||||
static TemporaryRef<FilterNode> Create(DrawTarget* aDT, ID2D1DeviceContext *aDC, FilterType aType);
|
||||
static TemporaryRef<FilterNode> Create(ID2D1DeviceContext *aDC, FilterType aType);
|
||||
|
||||
FilterNodeD2D1(DrawTarget* aDT, ID2D1Effect *aEffect, FilterType aType)
|
||||
: mDT(aDT)
|
||||
, mEffect(aEffect)
|
||||
FilterNodeD2D1(ID2D1Effect *aEffect, FilterType aType)
|
||||
: mEffect(aEffect)
|
||||
, mType(aType)
|
||||
{
|
||||
InitUnmappedProperties();
|
||||
@ -48,6 +48,12 @@ public:
|
||||
virtual void SetAttribute(uint32_t aIndex, const IntPoint &aValue);
|
||||
virtual void SetAttribute(uint32_t aIndex, const Matrix &aValue);
|
||||
|
||||
// Called by DrawTarget before it draws our OutputEffect, and recursively
|
||||
// by the filter nodes that have this filter as one of their inputs. This
|
||||
// gives us a chance to convert any input surfaces to the target format for
|
||||
// the DrawTarget that we will draw to.
|
||||
virtual void WillDraw(DrawTarget *aDT);
|
||||
|
||||
protected:
|
||||
friend class DrawTargetD2D1;
|
||||
friend class DrawTargetD2D;
|
||||
@ -58,8 +64,9 @@ protected:
|
||||
|
||||
void InitUnmappedProperties();
|
||||
|
||||
RefPtr<DrawTarget> mDT;
|
||||
RefPtr<ID2D1Effect> mEffect;
|
||||
std::vector<RefPtr<FilterNodeD2D1>> mInputFilters;
|
||||
std::vector<RefPtr<SourceSurface>> mInputSurfaces;
|
||||
FilterType mType;
|
||||
};
|
||||
|
||||
@ -67,9 +74,8 @@ class FilterNodeConvolveD2D1 : public FilterNodeD2D1
|
||||
{
|
||||
public:
|
||||
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeConvolveD2D1)
|
||||
FilterNodeConvolveD2D1(DrawTarget *aDT, ID2D1DeviceContext *aDC);
|
||||
FilterNodeConvolveD2D1(ID2D1DeviceContext *aDC);
|
||||
|
||||
virtual void SetInput(uint32_t aIndex, SourceSurface *aSurface);
|
||||
virtual void SetInput(uint32_t aIndex, FilterNode *aFilter);
|
||||
|
||||
virtual void SetAttribute(uint32_t aIndex, uint32_t aValue);
|
||||
@ -77,13 +83,14 @@ public:
|
||||
virtual void SetAttribute(uint32_t aIndex, const IntPoint &aValue);
|
||||
virtual void SetAttribute(uint32_t aIndex, const IntRect &aValue);
|
||||
|
||||
protected:
|
||||
virtual ID2D1Effect* InputEffect();
|
||||
|
||||
private:
|
||||
void UpdateChain();
|
||||
void UpdateOffset();
|
||||
void UpdateSourceRect();
|
||||
|
||||
RefPtr<ID2D1Image> mInput;
|
||||
RefPtr<ID2D1Effect> mInputEffect;
|
||||
RefPtr<ID2D1Effect> mFloodEffect;
|
||||
RefPtr<ID2D1Effect> mCompositeEffect;
|
||||
RefPtr<ID2D1Effect> mCropEffect;
|
||||
@ -98,7 +105,7 @@ class FilterNodeComponentTransferD2D1 : public FilterNodeD2D1
|
||||
{
|
||||
public:
|
||||
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeComponentTransferD2D1)
|
||||
FilterNodeComponentTransferD2D1(DrawTarget *aDT, ID2D1DeviceContext *aDC, ID2D1Effect *aEffect, FilterType aType);
|
||||
FilterNodeComponentTransferD2D1(ID2D1DeviceContext *aDC, ID2D1Effect *aEffect, FilterType aType);
|
||||
|
||||
protected:
|
||||
virtual ID2D1Effect* InputEffect() MOZ_OVERRIDE { return mPrePremultiplyEffect.get(); }
|
||||
|
Loading…
Reference in New Issue
Block a user