/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef MOZILLA_GFX_DRAWTARGETD2D1_H_ #define MOZILLA_GFX_DRAWTARGETD2D1_H_ #include "2D.h" #include #include #include "PathD2D.h" #include "HelpersD2D.h" #include #include #include struct IDWriteFactory; namespace mozilla { namespace gfx { class SourceSurfaceD2D1; const int32_t kLayerCacheSize1 = 5; class DrawTargetD2D1 : public DrawTarget { public: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawTargetD2D1) DrawTargetD2D1(); virtual ~DrawTargetD2D1(); virtual DrawTargetType GetType() const override { return DrawTargetType::HARDWARE_RASTER; } virtual BackendType GetBackendType() const { return BackendType::DIRECT2D1_1; } virtual already_AddRefed Snapshot(); virtual IntSize GetSize() { return mSize; } virtual void Flush(); virtual void DrawSurface(SourceSurface *aSurface, const Rect &aDest, const Rect &aSource, const DrawSurfaceOptions &aSurfOptions, const DrawOptions &aOptions); virtual void DrawFilter(FilterNode *aNode, const Rect &aSourceRect, const Point &aDestPoint, const DrawOptions &aOptions = DrawOptions()); virtual void DrawSurfaceWithShadow(SourceSurface *aSurface, const Point &aDest, const Color &aColor, const Point &aOffset, 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, const IntPoint &aDestination); virtual void FillRect(const Rect &aRect, const Pattern &aPattern, const DrawOptions &aOptions = DrawOptions()); virtual void StrokeRect(const Rect &aRect, const Pattern &aPattern, const StrokeOptions &aStrokeOptions = StrokeOptions(), const DrawOptions &aOptions = DrawOptions()); virtual void StrokeLine(const Point &aStart, const Point &aEnd, const Pattern &aPattern, const StrokeOptions &aStrokeOptions = StrokeOptions(), const DrawOptions &aOptions = DrawOptions()); virtual void Stroke(const Path *aPath, const Pattern &aPattern, const StrokeOptions &aStrokeOptions = StrokeOptions(), const DrawOptions &aOptions = DrawOptions()); virtual void Fill(const Path *aPath, const Pattern &aPattern, const DrawOptions &aOptions = DrawOptions()); virtual void FillGlyphs(ScaledFont *aFont, const GlyphBuffer &aBuffer, const Pattern &aPattern, const DrawOptions &aOptions = DrawOptions(), const GlyphRenderingOptions *aRenderingOptions = nullptr); virtual void Mask(const Pattern &aSource, const Pattern &aMask, const DrawOptions &aOptions = DrawOptions()); virtual void PushClip(const Path *aPath); virtual void PushClipRect(const Rect &aRect); virtual void PopClip(); virtual already_AddRefed CreateSourceSurfaceFromData(unsigned char *aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat) const; virtual already_AddRefed OptimizeSourceSurface(SourceSurface *aSurface) const; virtual already_AddRefed CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const { return nullptr; } virtual already_AddRefed CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const; virtual already_AddRefed CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const; virtual already_AddRefed CreateGradientStops(GradientStop *aStops, uint32_t aNumStops, ExtendMode aExtendMode = ExtendMode::CLAMP) const; virtual already_AddRefed CreateFilter(FilterType aType); virtual bool SupportsRegionClipping() const { return false; } virtual void *GetNativeSurface(NativeSurfaceType aType) { return nullptr; } bool Init(const IntSize &aSize, SurfaceFormat aFormat); bool Init(ID3D11Texture2D* aTexture, SurfaceFormat aFormat); uint32_t GetByteSize() const; already_AddRefed GetImageForSurface(SourceSurface *aSurface, Matrix &aSourceTransform, ExtendMode aExtendMode, const IntRect* aSourceRect = nullptr); already_AddRefed GetImageForSurface(SourceSurface *aSurface, ExtendMode aExtendMode) { Matrix mat; return GetImageForSurface(aSurface, mat, aExtendMode, nullptr); } static ID2D1Factory1 *factory(); static void CleanupD2D(); static IDWriteFactory *GetDWriteFactory(); operator std::string() const { std::stringstream stream; stream << "DrawTargetD2D 1.1 (" << this << ")"; return stream.str(); } static uint32_t GetMaxSurfaceSize() { return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; } static uint64_t mVRAMUsageDT; static uint64_t mVRAMUsageSS; private: friend class SourceSurfaceD2D1; typedef std::unordered_set TargetSet; // This function will mark the surface as changing, and make sure any // copy-on-write snapshots are notified. void MarkChanged(); void PrepareForDrawing(CompositionOp aOp, const Pattern &aPattern); void FinalizeDrawing(CompositionOp aOp, const Pattern &aPattern); void FlushTransformToDC() { if (mTransformDirty) { mDC->SetTransform(D2DMatrix(mTransform)); mTransformDirty = false; } } void AddDependencyOnSource(SourceSurfaceD2D1* aSource); // This returns the clipped geometry, in addition it returns aClipBounds which // represents the intersection of all pixel-aligned rectangular clips that // are currently set. The returned clipped geometry must be clipped by these // bounds to correctly reflect the total clip. This is in device space. already_AddRefed GetClippedGeometry(IntRect *aClipBounds); already_AddRefed GetInverseClippedGeometry(); bool GetDeviceSpaceClipRect(D2D1_RECT_F& aClipRect, bool& aIsPixelAligned); void PopAllClips(); void PushAllClips(); void PushClipsToDC(ID2D1DeviceContext *aDC, bool aForceIgnoreAlpha = false, const D2D1_RECT_F& aMaxRect = D2D1::InfiniteRect()); void PopClipsFromDC(ID2D1DeviceContext *aDC); already_AddRefed CreateTransparentBlackBrush(); already_AddRefed GetSolidColorBrush(const D2D_COLOR_F& aColor); already_AddRefed CreateBrushForPattern(const Pattern &aPattern, Float aAlpha = 1.0f); void PushD2DLayer(ID2D1DeviceContext *aDC, ID2D1Geometry *aGeometry, const D2D1_MATRIX_3X2_F &aTransform, bool aForceIgnoreAlpha = false, const D2D1_RECT_F& aLayerRect = D2D1::InfiniteRect()); IntSize mSize; RefPtr mDevice; RefPtr mTexture; RefPtr 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 mDC; RefPtr mBitmap; RefPtr mCommandList; RefPtr mBlendEffect; uint32_t mCommandListsCreated; RefPtr mSolidColorBrush; // We store this to prevent excessive SetTextRenderingParams calls. RefPtr mTextRenderingParams; // List of pushed clips. struct PushedClip { D2D1_RECT_F mBounds; union { // If mPath is non-null, the mTransform member will be used, otherwise // the mIsPixelAligned member is valid. D2D1_MATRIX_3X2_F mTransform; bool mIsPixelAligned; }; RefPtr mPath; }; std::vector mPushedClips; // The latest snapshot of this surface. This needs to be told when this // target is modified. We keep it alive as a cache. RefPtr mSnapshot; // A list of targets we need to flush when we're modified. TargetSet mDependentTargets; // A list of targets which have this object in their mDependentTargets set TargetSet mDependingOnTargets; // True of the current clip stack is pushed to the main RT. bool mClipsArePushed; static ID2D1Factory1 *mFactory; static IDWriteFactory *mDWriteFactory; }; } } #endif /* MOZILLA_GFX_DRAWTARGETD2D_H_ */