Bug 1220629 - Part 5: Implement PushLayer/PopLayer API for Direct2D 1.1. r=jrmuizel
--- a/gfx/2d/DrawTargetD2D1.cpp
+++ b/gfx/2d/DrawTargetD2D1.cpp
@@ -582,21 +582,17 @@ DrawTargetD2D1::FillGlyphs(ScaledFont *a
mDC->SetTransform(D2D1::IdentityMatrix());
mDC->GetGlyphRunWorldBounds(D2D1::Point2F(), &autoRun,
DWRITE_MEASURING_MODE_NATURAL, &userRect);
RefPtr<ID2D1PathGeometry> path;
D2DFactory()->CreatePathGeometry(getter_AddRefs(path));
RefPtr<ID2D1GeometrySink> sink;
path->Open(getter_AddRefs(sink));
- sink->BeginFigure(D2D1::Point2F(userRect.left, userRect.top), D2D1_FIGURE_BEGIN_FILLED);
- sink->AddLine(D2D1::Point2F(userRect.right, userRect.top));
- sink->AddLine(D2D1::Point2F(userRect.right, userRect.bottom));
- sink->AddLine(D2D1::Point2F(userRect.left, userRect.bottom));
- sink->EndFigure(D2D1_FIGURE_END_CLOSED);
+ AddRectToSink(sink, userRect);
sink->Close();
mDC->PushLayer(D2D1::LayerParameters1(D2D1::InfiniteRect(), path, D2D1_ANTIALIAS_MODE_ALIASED,
D2DMatrix(mTransform), 1.0f, nullptr,
D2D1_LAYER_OPTIONS1_INITIALIZE_FROM_BACKGROUND |
D2D1_LAYER_OPTIONS1_IGNORE_ALPHA), nullptr);
}
@@ -724,16 +720,92 @@ DrawTargetD2D1::PopClip()
mDC->PopLayer();
} else {
mDC->PopAxisAlignedClip();
}
}
CurrentLayer().mPushedClips.pop_back();
}
+void
+DrawTargetD2D1::PushLayer(bool aOpaque, Float aOpacity, SourceSurface* aMask,
+ const Matrix& aMaskTransform, const IntRect& aBounds,
+ bool aCopyBackground)
+{
+ D2D1_LAYER_OPTIONS1 options = D2D1_LAYER_OPTIONS1_NONE;
+
+ if (aOpaque) {
+ options |= D2D1_LAYER_OPTIONS1_IGNORE_ALPHA;
+ }
+ if (aCopyBackground) {
+ options |= D2D1_LAYER_OPTIONS1_INITIALIZE_FROM_BACKGROUND;
+ }
+
+ RefPtr<ID2D1BitmapBrush> mask;
+
+ Matrix maskTransform = aMaskTransform;
+
+ RefPtr<ID2D1PathGeometry> clip;
+ if (aMask) {
+ mDC->SetTransform(D2D1::IdentityMatrix());
+ mTransformDirty = true;
+
+ RefPtr<ID2D1Image> image = GetImageForSurface(aMask, maskTransform, ExtendMode::CLAMP);
+
+ // The mask is given in user space. Our layer will apply it in device space.
+ maskTransform = maskTransform * mTransform;
+
+ if (image) {
+ RefPtr<ID2D1Bitmap> bitmap;
+ image->QueryInterface((ID2D1Bitmap**)getter_AddRefs(bitmap));
+
+ mDC->CreateBitmapBrush(bitmap, D2D1::BitmapBrushProperties(), D2D1::BrushProperties(1.0f, D2DMatrix(maskTransform)), getter_AddRefs(mask));
+ MOZ_ASSERT(bitmap); // This should always be true since it was created for a surface.
+
+ factory()->CreatePathGeometry(getter_AddRefs(clip));
+ RefPtr<ID2D1GeometrySink> sink;
+ clip->Open(getter_AddRefs(sink));
+ AddRectToSink(sink, D2D1::RectF(0, 0, aMask->GetSize().width, aMask->GetSize().height));
+ sink->Close();
+ } else {
+ gfxCriticalError() << "Failed to get image for mask surface!";
+ }
+ }
+
+ PushAllClips();
+
+ mDC->PushLayer(D2D1::LayerParameters1(D2D1::InfiniteRect(), clip, D2D1_ANTIALIAS_MODE_ALIASED, D2DMatrix(maskTransform), aOpacity, mask, options), nullptr);
+ PushedLayer pushedLayer;
+ pushedLayer.mClipsArePushed = false;
+ pushedLayer.mIsOpaque = aOpaque;
+ mDC->CreateCommandList(getter_AddRefs(pushedLayer.mCurrentList));
+ mPushedLayers.push_back(pushedLayer);
+
+ mDC->SetTarget(CurrentTarget());
+}
+
+void
+DrawTargetD2D1::PopLayer()
+{
+ MOZ_ASSERT(CurrentLayer().mPushedClips.size() == 0);
+
+ RefPtr<ID2D1CommandList> list = CurrentLayer().mCurrentList;
+ mPushedLayers.pop_back();
+ mDC->SetTarget(CurrentTarget());
+
+ list->Close();
+ mDC->SetTransform(D2D1::IdentityMatrix());
+ mTransformDirty = true;
+
+ DCCommandSink sink(mDC);
+ list->Stream(&sink);
+
+ mDC->PopLayer();
+}
+
already_AddRefed<SourceSurface>
DrawTargetD2D1::CreateSourceSurfaceFromData(unsigned char *aData,
const IntSize &aSize,
int32_t aStride,
SurfaceFormat aFormat) const
{
RefPtr<ID2D1Bitmap1> bitmap;
@@ -1060,80 +1132,58 @@ DrawTargetD2D1::FinalizeDrawing(Composit
mDC->SetTransform(D2D1::IdentityMatrix());
mTransformDirty = true;
if (patternSupported) {
if (D2DSupportsCompositeMode(aOp)) {
D2D1_RECT_F rect;
bool isAligned;
- RefPtr<ID2D1Bitmap> tmpBitmap;
+ RefPtr<ID2D1Image> tmpImage;
bool clipIsComplex = CurrentLayer().mPushedClips.size() && !GetDeviceSpaceClipRect(rect, isAligned);
if (clipIsComplex) {
if (!IsOperatorBoundByMask(aOp)) {
- HRESULT hr = mDC->CreateBitmap(D2DIntSize(mSize), D2D1::BitmapProperties(D2DPixelFormat(mFormat)), getter_AddRefs(tmpBitmap));
- if (FAILED(hr)) {
- gfxCriticalError(CriticalLog::DefaultOptions(Factory::ReasonableSurfaceSize(mSize))) << "[D2D1.1] 6CreateBitmap failure " << mSize << " Code: " << hexa(hr) << " format " << (int)mFormat;
- // For now, crash in this scenario; this should happen because tmpBitmap is
- // null and CopyFromBitmap call below dereferences it.
- // return;
- }
- mDC->Flush();
-
- tmpBitmap->CopyFromBitmap(nullptr, mBitmap, nullptr);
+ tmpImage = GetImageForLayerContent();
}
} else {
PushAllClips();
}
mDC->DrawImage(source, D2D1_INTERPOLATION_MODE_NEAREST_NEIGHBOR, D2DCompositionMode(aOp));
- if (tmpBitmap) {
- RefPtr<ID2D1BitmapBrush> brush;
+ if (tmpImage) {
+ RefPtr<ID2D1ImageBrush> brush;
RefPtr<ID2D1Geometry> inverseGeom = GetInverseClippedGeometry();
- mDC->CreateBitmapBrush(tmpBitmap, getter_AddRefs(brush));
+ mDC->CreateImageBrush(tmpImage, D2D1::ImageBrushProperties(D2D1::RectF(0, 0, mSize.width, mSize.height)),
+ getter_AddRefs(brush));
mDC->SetPrimitiveBlend(D2D1_PRIMITIVE_BLEND_COPY);
mDC->FillGeometry(inverseGeom, brush);
mDC->SetPrimitiveBlend(D2D1_PRIMITIVE_BLEND_SOURCE_OVER);
}
return;
}
- if (!mBlendEffect) {
- HRESULT hr = mDC->CreateEffect(CLSID_D2D1Blend, getter_AddRefs(mBlendEffect));
+ RefPtr<ID2D1Effect> blendEffect;
+ HRESULT hr = mDC->CreateEffect(CLSID_D2D1Blend, getter_AddRefs(blendEffect));
- if (FAILED(hr) || !mBlendEffect) {
- gfxWarning() << "Failed to create blend effect!";
- return;
- }
- }
-
- RefPtr<ID2D1Bitmap> tmpBitmap;
- HRESULT hr = mDC->CreateBitmap(D2DIntSize(mSize), D2D1::BitmapProperties(D2DPixelFormat(mFormat)), getter_AddRefs(tmpBitmap));
- if (FAILED(hr)) {
- gfxCriticalError(CriticalLog::DefaultOptions(Factory::ReasonableSurfaceSize(mSize))) << "[D2D1.1] 5CreateBitmap failure " << mSize << " Code: " << hexa(hr) << " format " << (int)mFormat;
+ if (FAILED(hr) || !blendEffect) {
+ gfxWarning() << "Failed to create blend effect!";
return;
}
- // This flush is important since the copy method will not know about the context drawing to the surface.
- // We also need to pop all the clips to make sure any drawn content will have made it to the final bitmap.
- mDC->Flush();
+ RefPtr<ID2D1Image> tmpImage = GetImageForLayerContent();
- // We need to use a copy here because affects don't accept a surface on
- // both their in- and outputs.
- tmpBitmap->CopyFromBitmap(nullptr, mBitmap, nullptr);
-
- mBlendEffect->SetInput(0, tmpBitmap);
- mBlendEffect->SetInput(1, source);
- mBlendEffect->SetValue(D2D1_BLEND_PROP_MODE, D2DBlendMode(aOp));
+ blendEffect->SetInput(0, tmpImage);
+ blendEffect->SetInput(1, source);
+ blendEffect->SetValue(D2D1_BLEND_PROP_MODE, D2DBlendMode(aOp));
PushAllClips();
- mDC->DrawImage(mBlendEffect, D2D1_INTERPOLATION_MODE_NEAREST_NEIGHBOR, D2D1_COMPOSITE_MODE_BOUNDED_SOURCE_COPY);
+ mDC->DrawImage(blendEffect, D2D1_INTERPOLATION_MODE_NEAREST_NEIGHBOR, D2D1_COMPOSITE_MODE_BOUNDED_SOURCE_COPY);
return;
}
const RadialGradientPattern *pat = static_cast<const RadialGradientPattern*>(&aPattern);
if (pat->mCenter1 == pat->mCenter2 && pat->mRadius1 == pat->mRadius2) {
// Draw nothing!
return;
}
@@ -1200,16 +1250,45 @@ DrawTargetD2D1::GetDeviceSpaceClipRect(D
aClipRect = IntersectRect(aClipRect, iter->mBounds);
if (!iter->mIsPixelAligned) {
aIsPixelAligned = false;
}
}
return true;
}
+already_AddRefed<ID2D1Image>
+DrawTargetD2D1::GetImageForLayerContent()
+{
+ if (!CurrentLayer().mCurrentList) {
+ RefPtr<ID2D1Bitmap> tmpBitmap;
+ HRESULT hr = mDC->CreateBitmap(D2DIntSize(mSize), D2D1::BitmapProperties(D2DPixelFormat(mFormat)), getter_AddRefs(tmpBitmap));
+ if (FAILED(hr)) {
+ gfxCriticalError(CriticalLog::DefaultOptions(Factory::ReasonableSurfaceSize(mSize))) << "[D2D1.1] 6CreateBitmap failure " << mSize << " Code: " << hexa(hr) << " format " << (int)mFormat;
+ // For now, crash in this scenario; this should happen because tmpBitmap is
+ // null and CopyFromBitmap call below dereferences it.
+ // return;
+ }
+ mDC->Flush();
+
+ tmpBitmap->CopyFromBitmap(nullptr, mBitmap, nullptr);
+ return tmpBitmap.forget();
+ } else {
+ RefPtr<ID2D1CommandList> list = CurrentLayer().mCurrentList;
+ mDC->CreateCommandList(getter_AddRefs(CurrentLayer().mCurrentList));
+ mDC->SetTarget(CurrentTarget());
+ list->Close();
+
+ DCCommandSink sink(mDC);
+ list->Stream(&sink);
+
+ return list.forget();
+ }
+}
+
already_AddRefed<ID2D1Geometry>
DrawTargetD2D1::GetClippedGeometry(IntRect *aClipBounds)
{
if (mCurrentClippedGeometry) {
*aClipBounds = mCurrentClipBounds;
RefPtr<ID2D1Geometry> clippedGeometry(mCurrentClippedGeometry);
return clippedGeometry.forget();
}
--- a/gfx/2d/DrawTargetD2D1.h
+++ b/gfx/2d/DrawTargetD2D1.h
@@ -89,16 +89,22 @@ public:
const DrawOptions &aOptions = DrawOptions(),
const GlyphRenderingOptions *aRenderingOptions = nullptr) override;
virtual void Mask(const Pattern &aSource,
const Pattern &aMask,
const DrawOptions &aOptions = DrawOptions()) override;
virtual void PushClip(const Path *aPath) override;
virtual void PushClipRect(const Rect &aRect) override;
virtual void PopClip() override;
+ virtual void PushLayer(bool aOpaque, Float aOpacity,
+ SourceSurface* aMask,
+ const Matrix& aMaskTransform,
+ const IntRect& aBounds = IntRect(),
+ bool aCopyBackground = false) override;
+ virtual void PopLayer() override;
virtual already_AddRefed<SourceSurface> CreateSourceSurfaceFromData(unsigned char *aData,
const IntSize &aSize,
int32_t aStride,
SurfaceFormat aFormat) const override;
virtual already_AddRefed<SourceSurface> OptimizeSourceSurface(SourceSurface *aSurface) const override;
virtual already_AddRefed<SourceSurface>
@@ -112,16 +118,17 @@ public:
virtual already_AddRefed<GradientStops>
CreateGradientStops(GradientStop *aStops,
uint32_t aNumStops,
ExtendMode aExtendMode = ExtendMode::CLAMP) const override;
virtual already_AddRefed<FilterNode> CreateFilter(FilterType aType) override;
virtual bool SupportsRegionClipping() const override { return false; }
+ virtual bool IsCurrentGroupOpaque() override { return CurrentLayer().mIsOpaque; }
virtual void *GetNativeSurface(NativeSurfaceType aType) override { return nullptr; }
bool Init(const IntSize &aSize, SurfaceFormat aFormat);
bool Init(ID3D11Texture2D* aTexture, SurfaceFormat aFormat);
uint32_t GetByteSize() const;
already_AddRefed<ID2D1Image> GetImageForSurface(SourceSurface *aSurface, Matrix &aSourceTransform,
@@ -162,16 +169,19 @@ private:
void FlushTransformToDC() {
if (mTransformDirty) {
mDC->SetTransform(D2DMatrix(mTransform));
mTransformDirty = false;
}
}
void AddDependencyOnSource(SourceSurfaceD2D1* aSource);
+ // Must be called with all clips popped and an identity matrix set.
+ already_AddRefed<ID2D1Image> GetImageForLayerContent();
+
ID2D1Image* CurrentTarget()
{
if (CurrentLayer().mCurrentList) {
return CurrentLayer().mCurrentList;
}
return mBitmap;
}
@@ -206,17 +216,16 @@ private:
RefPtr<ID2D1Geometry> mCurrentClippedGeometry;
// This is only valid if mCurrentClippedGeometry is non-null. And will
// only be the intersection of all pixel-aligned retangular clips. This is in
// device space.
IntRect mCurrentClipBounds;
mutable RefPtr<ID2D1DeviceContext> mDC;
RefPtr<ID2D1Bitmap1> mBitmap;
RefPtr<ID2D1CommandList> mCommandList;
- RefPtr<ID2D1Effect> mBlendEffect;
RefPtr<ID2D1SolidColorBrush> mSolidColorBrush;
// We store this to prevent excessive SetTextRenderingParams calls.
RefPtr<IDWriteRenderingParams> mTextRenderingParams;
// List of pushed clips.
struct PushedClip
--- a/gfx/2d/HelpersD2D.h
+++ b/gfx/2d/HelpersD2D.h
@@ -691,12 +691,273 @@ CreatePartialBitmapForSurface(DataSource
aSourceTransform.PreScale(Float(size.width) / newSize.width,
Float(size.height) / newSize.height);
}
return bitmap.forget();
}
}
+static inline void AddRectToSink(ID2D1GeometrySink* aSink, const D2D1_RECT_F& aRect)
+{
+ aSink->BeginFigure(D2D1::Point2F(aRect.left, aRect.top), D2D1_FIGURE_BEGIN_FILLED);
+ aSink->AddLine(D2D1::Point2F(aRect.right, aRect.top));
+ aSink->AddLine(D2D1::Point2F(aRect.right, aRect.bottom));
+ aSink->AddLine(D2D1::Point2F(aRect.left, aRect.bottom));
+ aSink->EndFigure(D2D1_FIGURE_END_CLOSED);
+}
+
+class DCCommandSink : public ID2D1CommandSink
+{
+public:
+ DCCommandSink(ID2D1DeviceContext* aCtx) : mCtx(aCtx)
+ {
+ }
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(const IID &aIID, void **aPtr)
+ {
+ if (!aPtr) {
+ return E_POINTER;
+ }
+
+ if (aIID == IID_IUnknown) {
+ *aPtr = static_cast<IUnknown*>(this);
+ return S_OK;
+ } else if (aIID == IID_ID2D1CommandSink) {
+ *aPtr = static_cast<ID2D1CommandSink*>(this);
+ return S_OK;
+ }
+
+ return E_NOINTERFACE;
+ }
+
+ ULONG STDMETHODCALLTYPE AddRef()
+ {
+ return 1;
+ }
+
+ ULONG STDMETHODCALLTYPE Release()
+ {
+ return 1;
+ }
+
+ STDMETHODIMP BeginDraw()
+ {
+ // We don't want to do anything here!
+ return S_OK;
+ }
+ STDMETHODIMP EndDraw()
+ {
+ // We don't want to do anything here!
+ return S_OK;
+ }
+
+ STDMETHODIMP SetAntialiasMode(
+ D2D1_ANTIALIAS_MODE antialiasMode
+ )
+ {
+ mCtx->SetAntialiasMode(antialiasMode);
+ return S_OK;
+ }
+
+ STDMETHODIMP SetTags(D2D1_TAG tag1, D2D1_TAG tag2)
+ {
+ mCtx->SetTags(tag1, tag2);
+ return S_OK;
+ }
+
+ STDMETHODIMP SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE textAntialiasMode)
+ {
+ mCtx->SetTextAntialiasMode(textAntialiasMode);
+ return S_OK;
+ }
+
+ STDMETHODIMP SetTextRenderingParams(_In_opt_ IDWriteRenderingParams *textRenderingParams)
+ {
+ mCtx->SetTextRenderingParams(textRenderingParams);
+ return S_OK;
+ }
+
+ STDMETHODIMP SetTransform(_In_ CONST D2D1_MATRIX_3X2_F *transform)
+ {
+ mCtx->SetTransform(transform);
+ return S_OK;
+ }
+
+ STDMETHODIMP SetPrimitiveBlend(D2D1_PRIMITIVE_BLEND primitiveBlend)
+ {
+ mCtx->SetPrimitiveBlend(primitiveBlend);
+ return S_OK;
+ }
+
+ STDMETHODIMP SetUnitMode(D2D1_UNIT_MODE unitMode)
+ {
+ mCtx->SetUnitMode(unitMode);
+ return S_OK;
+ }
+
+ STDMETHODIMP Clear(_In_opt_ CONST D2D1_COLOR_F *color)
+ {
+ mCtx->Clear(color);
+ return S_OK;
+ }
+
+ STDMETHODIMP DrawGlyphRun(
+ D2D1_POINT_2F baselineOrigin,
+ _In_ CONST DWRITE_GLYPH_RUN *glyphRun,
+ _In_opt_ CONST DWRITE_GLYPH_RUN_DESCRIPTION *glyphRunDescription,
+ _In_ ID2D1Brush *foregroundBrush,
+ DWRITE_MEASURING_MODE measuringMode
+ )
+ {
+ mCtx->DrawGlyphRun(baselineOrigin, glyphRun, glyphRunDescription,
+ foregroundBrush, measuringMode);
+ return S_OK;
+ }
+
+ STDMETHODIMP DrawLine(
+ D2D1_POINT_2F point0,
+ D2D1_POINT_2F point1,
+ _In_ ID2D1Brush *brush,
+ FLOAT strokeWidth,
+ _In_opt_ ID2D1StrokeStyle *strokeStyle
+ )
+ {
+ mCtx->DrawLine(point0, point1, brush, strokeWidth, strokeStyle);
+ return S_OK;
+ }
+
+ STDMETHODIMP DrawGeometry(
+ _In_ ID2D1Geometry *geometry,
+ _In_ ID2D1Brush *brush,
+ FLOAT strokeWidth,
+ _In_opt_ ID2D1StrokeStyle *strokeStyle
+ )
+ {
+ mCtx->DrawGeometry(geometry, brush, strokeWidth, strokeStyle);
+ return S_OK;
+ }
+
+ STDMETHODIMP DrawRectangle(
+ _In_ CONST D2D1_RECT_F *rect,
+ _In_ ID2D1Brush *brush,
+ FLOAT strokeWidth,
+ _In_opt_ ID2D1StrokeStyle *strokeStyle
+ )
+ {
+ mCtx->DrawRectangle(rect, brush, strokeWidth, strokeStyle);
+ return S_OK;
+ }
+
+ STDMETHODIMP DrawBitmap(
+ _In_ ID2D1Bitmap *bitmap,
+ _In_opt_ CONST D2D1_RECT_F *destinationRectangle,
+ FLOAT opacity,
+ D2D1_INTERPOLATION_MODE interpolationMode,
+ _In_opt_ CONST D2D1_RECT_F *sourceRectangle,
+ _In_opt_ CONST D2D1_MATRIX_4X4_F *perspectiveTransform
+ )
+ {
+ mCtx->DrawBitmap(bitmap, destinationRectangle, opacity,
+ interpolationMode, sourceRectangle,
+ perspectiveTransform);
+ return S_OK;
+ }
+
+ STDMETHODIMP DrawImage(
+ _In_ ID2D1Image *image,
+ _In_opt_ CONST D2D1_POINT_2F *targetOffset,
+ _In_opt_ CONST D2D1_RECT_F *imageRectangle,
+ D2D1_INTERPOLATION_MODE interpolationMode,
+ D2D1_COMPOSITE_MODE compositeMode
+ )
+ {
+ mCtx->DrawImage(image, targetOffset, imageRectangle,
+ interpolationMode, compositeMode);
+ return S_OK;
+ }
+
+ STDMETHODIMP DrawGdiMetafile(
+ _In_ ID2D1GdiMetafile *gdiMetafile,
+ _In_opt_ CONST D2D1_POINT_2F *targetOffset
+ )
+ {
+ mCtx->DrawGdiMetafile(gdiMetafile, targetOffset);
+ return S_OK;
+ }
+
+ STDMETHODIMP FillMesh(
+ _In_ ID2D1Mesh *mesh,
+ _In_ ID2D1Brush *brush
+ )
+ {
+ mCtx->FillMesh(mesh, brush);
+ return S_OK;
+ }
+
+ STDMETHODIMP FillOpacityMask(
+ _In_ ID2D1Bitmap *opacityMask,
+ _In_ ID2D1Brush *brush,
+ _In_opt_ CONST D2D1_RECT_F *destinationRectangle,
+ _In_opt_ CONST D2D1_RECT_F *sourceRectangle
+ )
+ {
+ mCtx->FillOpacityMask(opacityMask, brush, destinationRectangle,
+ sourceRectangle);
+ return S_OK;
+ }
+
+ STDMETHODIMP FillGeometry(
+ _In_ ID2D1Geometry *geometry,
+ _In_ ID2D1Brush *brush,
+ _In_opt_ ID2D1Brush *opacityBrush
+ )
+ {
+ mCtx->FillGeometry(geometry, brush, opacityBrush);
+ return S_OK;
+ }
+
+ STDMETHODIMP FillRectangle(
+ _In_ CONST D2D1_RECT_F *rect,
+ _In_ ID2D1Brush *brush
+ )
+ {
+ mCtx->FillRectangle(rect, brush);
+ return S_OK;
+ }
+
+ STDMETHODIMP PushAxisAlignedClip(
+ _In_ CONST D2D1_RECT_F *clipRect,
+ D2D1_ANTIALIAS_MODE antialiasMode
+ )
+ {
+ mCtx->PushAxisAlignedClip(clipRect, antialiasMode);
+ return S_OK;
+ }
+
+ STDMETHODIMP PushLayer(
+ _In_ CONST D2D1_LAYER_PARAMETERS1 *layerParameters1,
+ _In_opt_ ID2D1Layer *layer
+ )
+ {
+ mCtx->PushLayer(layerParameters1, layer);
+ return S_OK;
+ }
+
+ STDMETHODIMP PopAxisAlignedClip()
+ {
+ mCtx->PopAxisAlignedClip();
+ return S_OK;
+ }
+
+ STDMETHODIMP PopLayer()
+ {
+ mCtx->PopLayer();
+ return S_OK;
+ }
+
+ ID2D1DeviceContext* mCtx;
+};
+
}
}
#endif /* MOZILLA_GFX_HELPERSD2D_H_ */