mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1220629 - Part 2: Prepare DrawTargetD2D1 for the possibilities of layers existing inside it. r=jrmuizel
This commit is contained in:
parent
c2450768f8
commit
413175f223
@ -31,7 +31,7 @@ ID2D1Factory1 *D2DFactory1()
|
|||||||
}
|
}
|
||||||
|
|
||||||
DrawTargetD2D1::DrawTargetD2D1()
|
DrawTargetD2D1::DrawTargetD2D1()
|
||||||
: mClipsArePushed(false)
|
: mPushedLayers(1)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,7 +267,7 @@ DrawTargetD2D1::ClearRect(const Rect &aRect)
|
|||||||
mDC->FillGeometry(geom, brush);
|
mDC->FillGeometry(geom, brush);
|
||||||
mDC->PopAxisAlignedClip();
|
mDC->PopAxisAlignedClip();
|
||||||
|
|
||||||
mDC->SetTarget(mBitmap);
|
mDC->SetTarget(CurrentTarget());
|
||||||
list->Close();
|
list->Close();
|
||||||
|
|
||||||
mDC->DrawImage(list, D2D1_INTERPOLATION_MODE_NEAREST_NEIGHBOR, D2D1_COMPOSITE_MODE_DESTINATION_OUT);
|
mDC->DrawImage(list, D2D1_INTERPOLATION_MODE_NEAREST_NEIGHBOR, D2D1_COMPOSITE_MODE_DESTINATION_OUT);
|
||||||
@ -515,7 +515,7 @@ DrawTargetD2D1::FillGlyphs(ScaledFont *aFont,
|
|||||||
PrepareForDrawing(aOptions.mCompositionOp, aPattern);
|
PrepareForDrawing(aOptions.mCompositionOp, aPattern);
|
||||||
|
|
||||||
bool forceClearType = false;
|
bool forceClearType = false;
|
||||||
if (mFormat == SurfaceFormat::B8G8R8A8 && mPermitSubpixelAA &&
|
if (!CurrentLayer().mIsOpaque && mPermitSubpixelAA &&
|
||||||
aOptions.mCompositionOp == CompositionOp::OP_OVER && aaMode == AntialiasMode::SUBPIXEL) {
|
aOptions.mCompositionOp == CompositionOp::OP_OVER && aaMode == AntialiasMode::SUBPIXEL) {
|
||||||
forceClearType = true;
|
forceClearType = true;
|
||||||
}
|
}
|
||||||
@ -538,7 +538,7 @@ DrawTargetD2D1::FillGlyphs(ScaledFont *aFont,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (d2dAAMode == D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE &&
|
if (d2dAAMode == D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE &&
|
||||||
mFormat != SurfaceFormat::B8G8R8X8 && !forceClearType) {
|
!CurrentLayer().mIsOpaque && !forceClearType) {
|
||||||
d2dAAMode = D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE;
|
d2dAAMode = D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -555,10 +555,10 @@ DrawTargetD2D1::FillGlyphs(ScaledFont *aFont,
|
|||||||
DWriteGlyphRunFromGlyphs(aBuffer, font, &autoRun);
|
DWriteGlyphRunFromGlyphs(aBuffer, font, &autoRun);
|
||||||
|
|
||||||
bool needsRepushedLayers = false;
|
bool needsRepushedLayers = false;
|
||||||
if (d2dAAMode == D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE && mFormat != SurfaceFormat::B8G8R8X8) {
|
if (forceClearType) {
|
||||||
D2D1_RECT_F rect;
|
D2D1_RECT_F rect;
|
||||||
bool isAligned;
|
bool isAligned;
|
||||||
needsRepushedLayers = mPushedClips.size() && !GetDeviceSpaceClipRect(rect, isAligned);
|
needsRepushedLayers = CurrentLayer().mPushedClips.size() && !GetDeviceSpaceClipRect(rect, isAligned);
|
||||||
|
|
||||||
// If we have a complex clip in our stack and we have a transparent
|
// If we have a complex clip in our stack and we have a transparent
|
||||||
// background, and subpixel AA is permitted, we need to repush our layer
|
// background, and subpixel AA is permitted, we need to repush our layer
|
||||||
@ -664,14 +664,14 @@ DrawTargetD2D1::PushClip(const Path *aPath)
|
|||||||
|
|
||||||
pathD2D->mGeometry->GetBounds(clip.mTransform, &clip.mBounds);
|
pathD2D->mGeometry->GetBounds(clip.mTransform, &clip.mBounds);
|
||||||
|
|
||||||
mPushedClips.push_back(clip);
|
CurrentLayer().mPushedClips.push_back(clip);
|
||||||
|
|
||||||
// The transform of clips is relative to the world matrix, since we use the total
|
// The transform of clips is relative to the world matrix, since we use the total
|
||||||
// transform for the clips, make the world matrix identity.
|
// transform for the clips, make the world matrix identity.
|
||||||
mDC->SetTransform(D2D1::IdentityMatrix());
|
mDC->SetTransform(D2D1::IdentityMatrix());
|
||||||
mTransformDirty = true;
|
mTransformDirty = true;
|
||||||
|
|
||||||
if (mClipsArePushed) {
|
if (CurrentLayer().mClipsArePushed) {
|
||||||
PushD2DLayer(mDC, pathD2D->mGeometry, clip.mTransform);
|
PushD2DLayer(mDC, pathD2D->mGeometry, clip.mTransform);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -704,12 +704,12 @@ DrawTargetD2D1::PushClipRect(const Rect &aRect)
|
|||||||
// Do not store the transform, just store the device space rectangle directly.
|
// Do not store the transform, just store the device space rectangle directly.
|
||||||
clip.mBounds = D2DRect(rect);
|
clip.mBounds = D2DRect(rect);
|
||||||
|
|
||||||
mPushedClips.push_back(clip);
|
CurrentLayer().mPushedClips.push_back(clip);
|
||||||
|
|
||||||
mDC->SetTransform(D2D1::IdentityMatrix());
|
mDC->SetTransform(D2D1::IdentityMatrix());
|
||||||
mTransformDirty = true;
|
mTransformDirty = true;
|
||||||
|
|
||||||
if (mClipsArePushed) {
|
if (CurrentLayer().mClipsArePushed) {
|
||||||
mDC->PushAxisAlignedClip(clip.mBounds, clip.mIsPixelAligned ? D2D1_ANTIALIAS_MODE_ALIASED : D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
|
mDC->PushAxisAlignedClip(clip.mBounds, clip.mIsPixelAligned ? D2D1_ANTIALIAS_MODE_ALIASED : D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -719,14 +719,14 @@ DrawTargetD2D1::PopClip()
|
|||||||
{
|
{
|
||||||
mCurrentClippedGeometry = nullptr;
|
mCurrentClippedGeometry = nullptr;
|
||||||
|
|
||||||
if (mClipsArePushed) {
|
if (CurrentLayer().mClipsArePushed) {
|
||||||
if (mPushedClips.back().mPath) {
|
if (CurrentLayer().mPushedClips.back().mPath) {
|
||||||
mDC->PopLayer();
|
mDC->PopLayer();
|
||||||
} else {
|
} else {
|
||||||
mDC->PopAxisAlignedClip();
|
mDC->PopAxisAlignedClip();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mPushedClips.pop_back();
|
CurrentLayer().mPushedClips.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<SourceSurface>
|
already_AddRefed<SourceSurface>
|
||||||
@ -878,10 +878,12 @@ DrawTargetD2D1::Init(ID3D11Texture2D* aTexture, SurfaceFormat aFormat)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
mDC->SetTarget(mBitmap);
|
mDC->SetTarget(CurrentTarget());
|
||||||
|
|
||||||
mDC->BeginDraw();
|
mDC->BeginDraw();
|
||||||
|
|
||||||
|
CurrentLayer().mIsOpaque = aFormat == SurfaceFormat::B8G8R8X8;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -922,7 +924,7 @@ DrawTargetD2D1::Init(const IntSize &aSize, SurfaceFormat aFormat)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
mDC->SetTarget(mBitmap);
|
mDC->SetTarget(CurrentTarget());
|
||||||
|
|
||||||
hr = mDC->CreateSolidColorBrush(D2D1::ColorF(0, 0), getter_AddRefs(mSolidColorBrush));
|
hr = mDC->CreateSolidColorBrush(D2D1::ColorF(0, 0), getter_AddRefs(mSolidColorBrush));
|
||||||
|
|
||||||
@ -933,6 +935,8 @@ DrawTargetD2D1::Init(const IntSize &aSize, SurfaceFormat aFormat)
|
|||||||
|
|
||||||
mDC->BeginDraw();
|
mDC->BeginDraw();
|
||||||
|
|
||||||
|
CurrentLayer().mIsOpaque = aFormat == SurfaceFormat::B8G8R8X8;
|
||||||
|
|
||||||
mDC->Clear();
|
mDC->Clear();
|
||||||
|
|
||||||
mFormat = aFormat;
|
mFormat = aFormat;
|
||||||
@ -1048,7 +1052,7 @@ DrawTargetD2D1::FinalizeDrawing(CompositionOp aOp, const Pattern &aPattern)
|
|||||||
|
|
||||||
PopAllClips();
|
PopAllClips();
|
||||||
|
|
||||||
mDC->SetTarget(mBitmap);
|
mDC->SetTarget(CurrentTarget());
|
||||||
mCommandList->Close();
|
mCommandList->Close();
|
||||||
|
|
||||||
RefPtr<ID2D1CommandList> source = mCommandList;
|
RefPtr<ID2D1CommandList> source = mCommandList;
|
||||||
@ -1062,7 +1066,7 @@ DrawTargetD2D1::FinalizeDrawing(CompositionOp aOp, const Pattern &aPattern)
|
|||||||
D2D1_RECT_F rect;
|
D2D1_RECT_F rect;
|
||||||
bool isAligned;
|
bool isAligned;
|
||||||
RefPtr<ID2D1Bitmap> tmpBitmap;
|
RefPtr<ID2D1Bitmap> tmpBitmap;
|
||||||
bool clipIsComplex = mPushedClips.size() && !GetDeviceSpaceClipRect(rect, isAligned);
|
bool clipIsComplex = CurrentLayer().mPushedClips.size() && !GetDeviceSpaceClipRect(rect, isAligned);
|
||||||
|
|
||||||
if (clipIsComplex) {
|
if (clipIsComplex) {
|
||||||
if (!IsOperatorBoundByMask(aOp)) {
|
if (!IsOperatorBoundByMask(aOp)) {
|
||||||
@ -1184,12 +1188,12 @@ IntersectRect(const D2D1_RECT_F& aRect1, const D2D1_RECT_F& aRect2)
|
|||||||
bool
|
bool
|
||||||
DrawTargetD2D1::GetDeviceSpaceClipRect(D2D1_RECT_F& aClipRect, bool& aIsPixelAligned)
|
DrawTargetD2D1::GetDeviceSpaceClipRect(D2D1_RECT_F& aClipRect, bool& aIsPixelAligned)
|
||||||
{
|
{
|
||||||
if (!mPushedClips.size()) {
|
if (!CurrentLayer().mPushedClips.size()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
aClipRect = D2D1::RectF(0, 0, mSize.width, mSize.height);
|
aClipRect = D2D1::RectF(0, 0, mSize.width, mSize.height);
|
||||||
for (auto iter = mPushedClips.begin();iter != mPushedClips.end(); iter++) {
|
for (auto iter = CurrentLayer().mPushedClips.begin();iter != CurrentLayer().mPushedClips.end(); iter++) {
|
||||||
if (iter->mPath) {
|
if (iter->mPath) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1210,7 +1214,7 @@ DrawTargetD2D1::GetClippedGeometry(IntRect *aClipBounds)
|
|||||||
return clippedGeometry.forget();
|
return clippedGeometry.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_ASSERT(mPushedClips.size());
|
MOZ_ASSERT(CurrentLayer().mPushedClips.size());
|
||||||
|
|
||||||
mCurrentClipBounds = IntRect(IntPoint(0, 0), mSize);
|
mCurrentClipBounds = IntRect(IntPoint(0, 0), mSize);
|
||||||
|
|
||||||
@ -1218,7 +1222,7 @@ DrawTargetD2D1::GetClippedGeometry(IntRect *aClipBounds)
|
|||||||
RefPtr<ID2D1Geometry> pathGeom;
|
RefPtr<ID2D1Geometry> pathGeom;
|
||||||
D2D1_RECT_F pathRect;
|
D2D1_RECT_F pathRect;
|
||||||
bool pathRectIsAxisAligned = false;
|
bool pathRectIsAxisAligned = false;
|
||||||
auto iter = mPushedClips.begin();
|
auto iter = CurrentLayer().mPushedClips.begin();
|
||||||
|
|
||||||
if (iter->mPath) {
|
if (iter->mPath) {
|
||||||
pathGeom = GetTransformedGeometry(iter->mPath->GetGeometry(), iter->mTransform);
|
pathGeom = GetTransformedGeometry(iter->mPath->GetGeometry(), iter->mTransform);
|
||||||
@ -1228,7 +1232,7 @@ DrawTargetD2D1::GetClippedGeometry(IntRect *aClipBounds)
|
|||||||
}
|
}
|
||||||
|
|
||||||
iter++;
|
iter++;
|
||||||
for (;iter != mPushedClips.end(); iter++) {
|
for (;iter != CurrentLayer().mPushedClips.end(); iter++) {
|
||||||
// Do nothing but add it to the current clip bounds.
|
// Do nothing but add it to the current clip bounds.
|
||||||
if (!iter->mPath && iter->mIsPixelAligned) {
|
if (!iter->mPath && iter->mIsPixelAligned) {
|
||||||
mCurrentClipBounds.IntersectRect(mCurrentClipBounds,
|
mCurrentClipBounds.IntersectRect(mCurrentClipBounds,
|
||||||
@ -1313,20 +1317,20 @@ DrawTargetD2D1::GetInverseClippedGeometry()
|
|||||||
void
|
void
|
||||||
DrawTargetD2D1::PopAllClips()
|
DrawTargetD2D1::PopAllClips()
|
||||||
{
|
{
|
||||||
if (mClipsArePushed) {
|
if (CurrentLayer().mClipsArePushed) {
|
||||||
PopClipsFromDC(mDC);
|
PopClipsFromDC(mDC);
|
||||||
|
|
||||||
mClipsArePushed = false;
|
CurrentLayer().mClipsArePushed = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DrawTargetD2D1::PushAllClips()
|
DrawTargetD2D1::PushAllClips()
|
||||||
{
|
{
|
||||||
if (!mClipsArePushed) {
|
if (!CurrentLayer().mClipsArePushed) {
|
||||||
PushClipsToDC(mDC);
|
PushClipsToDC(mDC);
|
||||||
|
|
||||||
mClipsArePushed = true;
|
CurrentLayer().mClipsArePushed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1336,8 +1340,7 @@ DrawTargetD2D1::PushClipsToDC(ID2D1DeviceContext *aDC, bool aForceIgnoreAlpha, c
|
|||||||
mDC->SetTransform(D2D1::IdentityMatrix());
|
mDC->SetTransform(D2D1::IdentityMatrix());
|
||||||
mTransformDirty = true;
|
mTransformDirty = true;
|
||||||
|
|
||||||
for (std::vector<PushedClip>::iterator iter = mPushedClips.begin();
|
for (auto iter = CurrentLayer().mPushedClips.begin(); iter != CurrentLayer().mPushedClips.end(); iter++) {
|
||||||
iter != mPushedClips.end(); iter++) {
|
|
||||||
if (iter->mPath) {
|
if (iter->mPath) {
|
||||||
PushD2DLayer(aDC, iter->mPath->mGeometry, iter->mTransform, aForceIgnoreAlpha, aMaxRect);
|
PushD2DLayer(aDC, iter->mPath->mGeometry, iter->mTransform, aForceIgnoreAlpha, aMaxRect);
|
||||||
} else {
|
} else {
|
||||||
@ -1349,8 +1352,8 @@ DrawTargetD2D1::PushClipsToDC(ID2D1DeviceContext *aDC, bool aForceIgnoreAlpha, c
|
|||||||
void
|
void
|
||||||
DrawTargetD2D1::PopClipsFromDC(ID2D1DeviceContext *aDC)
|
DrawTargetD2D1::PopClipsFromDC(ID2D1DeviceContext *aDC)
|
||||||
{
|
{
|
||||||
for (int i = mPushedClips.size() - 1; i >= 0; i--) {
|
for (int i = CurrentLayer().mPushedClips.size() - 1; i >= 0; i--) {
|
||||||
if (mPushedClips[i].mPath) {
|
if (CurrentLayer().mPushedClips[i].mPath) {
|
||||||
aDC->PopLayer();
|
aDC->PopLayer();
|
||||||
} else {
|
} else {
|
||||||
aDC->PopAxisAlignedClip();
|
aDC->PopAxisAlignedClip();
|
||||||
|
@ -167,14 +167,24 @@ private:
|
|||||||
}
|
}
|
||||||
void AddDependencyOnSource(SourceSurfaceD2D1* aSource);
|
void AddDependencyOnSource(SourceSurfaceD2D1* aSource);
|
||||||
|
|
||||||
|
ID2D1Image* CurrentTarget()
|
||||||
|
{
|
||||||
|
if (CurrentLayer().mCurrentList) {
|
||||||
|
return CurrentLayer().mCurrentList;
|
||||||
|
}
|
||||||
|
return mBitmap;
|
||||||
|
}
|
||||||
|
|
||||||
// This returns the clipped geometry, in addition it returns aClipBounds which
|
// This returns the clipped geometry, in addition it returns aClipBounds which
|
||||||
// represents the intersection of all pixel-aligned rectangular clips that
|
// represents the intersection of all pixel-aligned rectangular clips that
|
||||||
// are currently set. The returned clipped geometry must be clipped by these
|
// are currently set. The returned clipped geometry must be clipped by these
|
||||||
// bounds to correctly reflect the total clip. This is in device space.
|
// bounds to correctly reflect the total clip. This is in device space and
|
||||||
|
// only for clips applied to the -current layer-.
|
||||||
already_AddRefed<ID2D1Geometry> GetClippedGeometry(IntRect *aClipBounds);
|
already_AddRefed<ID2D1Geometry> GetClippedGeometry(IntRect *aClipBounds);
|
||||||
|
|
||||||
already_AddRefed<ID2D1Geometry> GetInverseClippedGeometry();
|
already_AddRefed<ID2D1Geometry> GetInverseClippedGeometry();
|
||||||
|
|
||||||
|
// This gives the device space clip rect applied to the -current layer-.
|
||||||
bool GetDeviceSpaceClipRect(D2D1_RECT_F& aClipRect, bool& aIsPixelAligned);
|
bool GetDeviceSpaceClipRect(D2D1_RECT_F& aClipRect, bool& aIsPixelAligned);
|
||||||
|
|
||||||
void PopAllClips();
|
void PopAllClips();
|
||||||
@ -220,7 +230,23 @@ private:
|
|||||||
};
|
};
|
||||||
RefPtr<PathD2D> mPath;
|
RefPtr<PathD2D> mPath;
|
||||||
};
|
};
|
||||||
std::vector<PushedClip> mPushedClips;
|
|
||||||
|
// List of pushed layers.
|
||||||
|
struct PushedLayer
|
||||||
|
{
|
||||||
|
PushedLayer() : mClipsArePushed(false), mIsOpaque(false) {}
|
||||||
|
|
||||||
|
std::vector<PushedClip> mPushedClips;
|
||||||
|
RefPtr<ID2D1CommandList> mCurrentList;
|
||||||
|
// True if the current clip stack is pushed to the CurrentTarget().
|
||||||
|
bool mClipsArePushed;
|
||||||
|
bool mIsOpaque;
|
||||||
|
};
|
||||||
|
std::vector<PushedLayer> mPushedLayers;
|
||||||
|
PushedLayer& CurrentLayer()
|
||||||
|
{
|
||||||
|
return mPushedLayers.back();
|
||||||
|
}
|
||||||
|
|
||||||
// The latest snapshot of this surface. This needs to be told when this
|
// The latest snapshot of this surface. This needs to be told when this
|
||||||
// target is modified. We keep it alive as a cache.
|
// target is modified. We keep it alive as a cache.
|
||||||
@ -230,8 +256,6 @@ private:
|
|||||||
// A list of targets which have this object in their mDependentTargets set
|
// A list of targets which have this object in their mDependentTargets set
|
||||||
TargetSet mDependingOnTargets;
|
TargetSet mDependingOnTargets;
|
||||||
|
|
||||||
// True of the current clip stack is pushed to the main RT.
|
|
||||||
bool mClipsArePushed;
|
|
||||||
static ID2D1Factory1 *mFactory;
|
static ID2D1Factory1 *mFactory;
|
||||||
static IDWriteFactory *mDWriteFactory;
|
static IDWriteFactory *mDWriteFactory;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user