michael@0: /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef MOZILLA_GFX_DRAWTARGETD2D_H_ michael@0: #define MOZILLA_GFX_DRAWTARGETD2D_H_ michael@0: michael@0: #include "2D.h" michael@0: #include "PathD2D.h" michael@0: #include michael@0: #include "HelpersD2D.h" michael@0: michael@0: #include michael@0: #include michael@0: michael@0: #ifdef _MSC_VER michael@0: #include michael@0: #else michael@0: #include michael@0: #endif michael@0: michael@0: struct IDWriteFactory; michael@0: michael@0: namespace mozilla { michael@0: namespace gfx { michael@0: michael@0: class SourceSurfaceD2DTarget; michael@0: class SourceSurfaceD2D; michael@0: class GradientStopsD2D; michael@0: class ScaledFontDWrite; michael@0: michael@0: const int32_t kLayerCacheSize = 5; michael@0: michael@0: struct PrivateD3D10DataD2D michael@0: { michael@0: RefPtr mEffect; michael@0: RefPtr mInputLayout; michael@0: RefPtr mVB; michael@0: RefPtr mBlendStates[size_t(CompositionOp::OP_COUNT)]; michael@0: }; michael@0: michael@0: class DrawTargetD2D : public DrawTarget michael@0: { michael@0: public: michael@0: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawTargetD2D) michael@0: DrawTargetD2D(); michael@0: virtual ~DrawTargetD2D(); michael@0: michael@0: virtual BackendType GetType() const { return BackendType::DIRECT2D; } michael@0: virtual TemporaryRef Snapshot(); michael@0: virtual IntSize GetSize() { return mSize; } michael@0: michael@0: virtual void Flush(); michael@0: virtual void DrawSurface(SourceSurface *aSurface, michael@0: const Rect &aDest, michael@0: const Rect &aSource, michael@0: const DrawSurfaceOptions &aSurfOptions = DrawSurfaceOptions(), michael@0: const DrawOptions &aOptions = DrawOptions()); michael@0: virtual void DrawFilter(FilterNode *aNode, michael@0: const Rect &aSourceRect, michael@0: const Point &aDestPoint, michael@0: const DrawOptions &aOptions = DrawOptions()); michael@0: virtual void DrawSurfaceWithShadow(SourceSurface *aSurface, michael@0: const Point &aDest, michael@0: const Color &aColor, michael@0: const Point &aOffset, michael@0: Float aSigma, michael@0: CompositionOp aOperator); michael@0: virtual void ClearRect(const Rect &aRect); michael@0: virtual void MaskSurface(const Pattern &aSource, michael@0: SourceSurface *aMask, michael@0: Point aOffset, michael@0: const DrawOptions &aOptions = DrawOptions()); michael@0: michael@0: michael@0: virtual void CopySurface(SourceSurface *aSurface, michael@0: const IntRect &aSourceRect, michael@0: const IntPoint &aDestination); michael@0: michael@0: virtual void FillRect(const Rect &aRect, michael@0: const Pattern &aPattern, michael@0: const DrawOptions &aOptions = DrawOptions()); michael@0: virtual void StrokeRect(const Rect &aRect, michael@0: const Pattern &aPattern, michael@0: const StrokeOptions &aStrokeOptions = StrokeOptions(), michael@0: const DrawOptions &aOptions = DrawOptions()); michael@0: virtual void StrokeLine(const Point &aStart, michael@0: const Point &aEnd, michael@0: const Pattern &aPattern, michael@0: const StrokeOptions &aStrokeOptions = StrokeOptions(), michael@0: const DrawOptions &aOptions = DrawOptions()); michael@0: virtual void Stroke(const Path *aPath, michael@0: const Pattern &aPattern, michael@0: const StrokeOptions &aStrokeOptions = StrokeOptions(), michael@0: const DrawOptions &aOptions = DrawOptions()); michael@0: virtual void Fill(const Path *aPath, michael@0: const Pattern &aPattern, michael@0: const DrawOptions &aOptions = DrawOptions()); michael@0: virtual void FillGlyphs(ScaledFont *aFont, michael@0: const GlyphBuffer &aBuffer, michael@0: const Pattern &aPattern, michael@0: const DrawOptions &aOptions = DrawOptions(), michael@0: const GlyphRenderingOptions *aRenderingOptions = nullptr); michael@0: virtual void Mask(const Pattern &aSource, michael@0: const Pattern &aMask, michael@0: const DrawOptions &aOptions = DrawOptions()); michael@0: virtual void PushClip(const Path *aPath); michael@0: virtual void PushClipRect(const Rect &aRect); michael@0: virtual void PopClip(); michael@0: michael@0: virtual TemporaryRef CreateSourceSurfaceFromData(unsigned char *aData, michael@0: const IntSize &aSize, michael@0: int32_t aStride, michael@0: SurfaceFormat aFormat) const; michael@0: virtual TemporaryRef OptimizeSourceSurface(SourceSurface *aSurface) const; michael@0: michael@0: virtual TemporaryRef michael@0: CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const; michael@0: michael@0: virtual TemporaryRef michael@0: CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const; michael@0: michael@0: virtual TemporaryRef CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const; michael@0: michael@0: virtual TemporaryRef michael@0: CreateGradientStops(GradientStop *aStops, michael@0: uint32_t aNumStops, michael@0: ExtendMode aExtendMode = ExtendMode::CLAMP) const; michael@0: michael@0: virtual TemporaryRef CreateFilter(FilterType aType); michael@0: michael@0: virtual void *GetNativeSurface(NativeSurfaceType aType); michael@0: michael@0: bool Init(const IntSize &aSize, SurfaceFormat aFormat); michael@0: bool Init(ID3D10Texture2D *aTexture, SurfaceFormat aFormat); michael@0: bool InitD3D10Data(); michael@0: uint32_t GetByteSize() const; michael@0: TemporaryRef GetCachedLayer(); michael@0: void PopCachedLayer(ID2D1RenderTarget *aRT); michael@0: michael@0: #ifdef USE_D2D1_1 michael@0: TemporaryRef GetImageForSurface(SourceSurface *aSurface); michael@0: #endif michael@0: michael@0: static ID2D1Factory *factory(); michael@0: static void CleanupD2D(); michael@0: static IDWriteFactory *GetDWriteFactory(); michael@0: ID2D1RenderTarget *GetRT() { return mRT; } michael@0: michael@0: operator std::string() const { michael@0: std::stringstream stream; michael@0: stream << "DrawTargetD2D(" << this << ")"; michael@0: return stream.str(); michael@0: } michael@0: michael@0: static uint64_t mVRAMUsageDT; michael@0: static uint64_t mVRAMUsageSS; michael@0: michael@0: private: michael@0: TemporaryRef michael@0: GetBitmapForSurface(SourceSurface *aSurface, michael@0: Rect &aSource); michael@0: friend class AutoSaveRestoreClippedOut; michael@0: friend class SourceSurfaceD2DTarget; michael@0: michael@0: #ifdef _MSC_VER michael@0: typedef stdext::hash_set TargetSet; michael@0: #else michael@0: typedef std::unordered_set TargetSet; michael@0: #endif michael@0: michael@0: bool InitD2DRenderTarget(); michael@0: void PrepareForDrawing(ID2D1RenderTarget *aRT); michael@0: michael@0: // This function will mark the surface as changing, and make sure any michael@0: // copy-on-write snapshots are notified. michael@0: void MarkChanged(); michael@0: void FlushTransformToRT() { michael@0: if (mTransformDirty) { michael@0: mRT->SetTransform(D2DMatrix(mTransform)); michael@0: mTransformDirty = false; michael@0: } michael@0: } michael@0: void AddDependencyOnSource(SourceSurfaceD2DTarget* aSource); michael@0: michael@0: ID3D10BlendState *GetBlendStateForOperator(CompositionOp aOperator); michael@0: ID2D1RenderTarget *GetRTForOperation(CompositionOp aOperator, const Pattern &aPattern); michael@0: void FinalizeRTForOperation(CompositionOp aOperator, const Pattern &aPattern, const Rect &aBounds); void EnsureViews(); michael@0: void PopAllClips(); michael@0: void PushClipsToRT(ID2D1RenderTarget *aRT); michael@0: void PopClipsFromRT(ID2D1RenderTarget *aRT); michael@0: michael@0: // This function ensures mCurrentClipMaskTexture contains a texture containing michael@0: // a mask corresponding with the current DrawTarget clip. See michael@0: // GetClippedGeometry for a description of aClipBounds. michael@0: void EnsureClipMaskTexture(IntRect *aClipBounds); michael@0: michael@0: bool FillGlyphsManual(ScaledFontDWrite *aFont, michael@0: const GlyphBuffer &aBuffer, michael@0: const Color &aColor, michael@0: IDWriteRenderingParams *aParams, michael@0: const DrawOptions &aOptions = DrawOptions()); michael@0: michael@0: TemporaryRef CreateRTForTexture(ID3D10Texture2D *aTexture, SurfaceFormat aFormat); michael@0: michael@0: // This returns the clipped geometry, in addition it returns aClipBounds which michael@0: // represents the intersection of all pixel-aligned rectangular clips that michael@0: // are currently set. The returned clipped geometry must be clipped by these michael@0: // bounds to correctly reflect the total clip. This is in device space. michael@0: TemporaryRef GetClippedGeometry(IntRect *aClipBounds); michael@0: michael@0: bool GetDeviceSpaceClipRect(D2D1_RECT_F& aClipRect, bool& aIsPixelAligned); michael@0: michael@0: TemporaryRef CreateBrushForPattern(const Pattern &aPattern, Float aAlpha = 1.0f); michael@0: michael@0: TemporaryRef CreateGradientTexture(const GradientStopsD2D *aStops); michael@0: TemporaryRef CreateTextureForAnalysis(IDWriteGlyphRunAnalysis *aAnalysis, const IntRect &aBounds); michael@0: michael@0: void SetupEffectForRadialGradient(const RadialGradientPattern *aPattern); michael@0: void SetupStateForRendering(); michael@0: michael@0: // Set the scissor rect to a certain IntRects, resets the scissor rect to michael@0: // surface bounds when nullptr is specified. michael@0: void SetScissorToRect(IntRect *aRect); michael@0: michael@0: void PushD2DLayer(ID2D1RenderTarget *aRT, ID2D1Geometry *aGeometry, ID2D1Layer *aLayer, const D2D1_MATRIX_3X2_F &aTransform); michael@0: michael@0: static const uint32_t test = 4; michael@0: michael@0: IntSize mSize; michael@0: michael@0: RefPtr mDevice; michael@0: RefPtr mTexture; michael@0: RefPtr mCurrentClipMaskTexture; michael@0: RefPtr mCurrentClippedGeometry; michael@0: // This is only valid if mCurrentClippedGeometry is non-null. And will michael@0: // only be the intersection of all pixel-aligned retangular clips. This is in michael@0: // device space. michael@0: IntRect mCurrentClipBounds; michael@0: mutable RefPtr mRT; michael@0: michael@0: // We store this to prevent excessive SetTextRenderingParams calls. michael@0: RefPtr mTextRenderingParams; michael@0: michael@0: // Temporary texture and render target used for supporting alternative operators. michael@0: RefPtr mTempTexture; michael@0: RefPtr mRTView; michael@0: RefPtr mSRView; michael@0: RefPtr mTempRT; michael@0: RefPtr mTempRTView; michael@0: michael@0: // List of pushed clips. michael@0: struct PushedClip michael@0: { michael@0: RefPtr mLayer; michael@0: D2D1_RECT_F mBounds; michael@0: union { michael@0: // If mPath is non-nullptr, the mTransform member will be used, otherwise michael@0: // the mIsPixelAligned member is valid. michael@0: D2D1_MATRIX_3X2_F mTransform; michael@0: bool mIsPixelAligned; michael@0: }; michael@0: RefPtr mPath; michael@0: }; michael@0: std::vector mPushedClips; michael@0: michael@0: // We cache ID2D1Layer objects as it causes D2D to keep around textures that michael@0: // serve as the temporary surfaces for these operations. As texture creation michael@0: // is quite expensive this considerably improved performance. michael@0: // Careful here, RAII will not ensure destruction of the RefPtrs. michael@0: RefPtr mCachedLayers[kLayerCacheSize]; michael@0: uint32_t mCurrentCachedLayer; michael@0: michael@0: // The latest snapshot of this surface. This needs to be told when this michael@0: // target is modified. We keep it alive as a cache. michael@0: RefPtr mSnapshot; michael@0: // A list of targets we need to flush when we're modified. michael@0: TargetSet mDependentTargets; michael@0: // A list of targets which have this object in their mDependentTargets set michael@0: TargetSet mDependingOnTargets; michael@0: michael@0: // True of the current clip stack is pushed to the main RT. michael@0: bool mClipsArePushed; michael@0: PrivateD3D10DataD2D *mPrivateData; michael@0: static ID2D1Factory *mFactory; michael@0: static IDWriteFactory *mDWriteFactory; michael@0: }; michael@0: michael@0: } michael@0: } michael@0: michael@0: #endif /* MOZILLA_GFX_DRAWTARGETD2D_H_ */