1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/2d/DrawTargetD2D.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,293 @@ 1.4 +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- 1.5 + * This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#ifndef MOZILLA_GFX_DRAWTARGETD2D_H_ 1.10 +#define MOZILLA_GFX_DRAWTARGETD2D_H_ 1.11 + 1.12 +#include "2D.h" 1.13 +#include "PathD2D.h" 1.14 +#include <d3d10_1.h> 1.15 +#include "HelpersD2D.h" 1.16 + 1.17 +#include <vector> 1.18 +#include <sstream> 1.19 + 1.20 +#ifdef _MSC_VER 1.21 +#include <hash_set> 1.22 +#else 1.23 +#include <unordered_set> 1.24 +#endif 1.25 + 1.26 +struct IDWriteFactory; 1.27 + 1.28 +namespace mozilla { 1.29 +namespace gfx { 1.30 + 1.31 +class SourceSurfaceD2DTarget; 1.32 +class SourceSurfaceD2D; 1.33 +class GradientStopsD2D; 1.34 +class ScaledFontDWrite; 1.35 + 1.36 +const int32_t kLayerCacheSize = 5; 1.37 + 1.38 +struct PrivateD3D10DataD2D 1.39 +{ 1.40 + RefPtr<ID3D10Effect> mEffect; 1.41 + RefPtr<ID3D10InputLayout> mInputLayout; 1.42 + RefPtr<ID3D10Buffer> mVB; 1.43 + RefPtr<ID3D10BlendState> mBlendStates[size_t(CompositionOp::OP_COUNT)]; 1.44 +}; 1.45 + 1.46 +class DrawTargetD2D : public DrawTarget 1.47 +{ 1.48 +public: 1.49 + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawTargetD2D) 1.50 + DrawTargetD2D(); 1.51 + virtual ~DrawTargetD2D(); 1.52 + 1.53 + virtual BackendType GetType() const { return BackendType::DIRECT2D; } 1.54 + virtual TemporaryRef<SourceSurface> Snapshot(); 1.55 + virtual IntSize GetSize() { return mSize; } 1.56 + 1.57 + virtual void Flush(); 1.58 + virtual void DrawSurface(SourceSurface *aSurface, 1.59 + const Rect &aDest, 1.60 + const Rect &aSource, 1.61 + const DrawSurfaceOptions &aSurfOptions = DrawSurfaceOptions(), 1.62 + const DrawOptions &aOptions = DrawOptions()); 1.63 + virtual void DrawFilter(FilterNode *aNode, 1.64 + const Rect &aSourceRect, 1.65 + const Point &aDestPoint, 1.66 + const DrawOptions &aOptions = DrawOptions()); 1.67 + virtual void DrawSurfaceWithShadow(SourceSurface *aSurface, 1.68 + const Point &aDest, 1.69 + const Color &aColor, 1.70 + const Point &aOffset, 1.71 + Float aSigma, 1.72 + CompositionOp aOperator); 1.73 + virtual void ClearRect(const Rect &aRect); 1.74 + virtual void MaskSurface(const Pattern &aSource, 1.75 + SourceSurface *aMask, 1.76 + Point aOffset, 1.77 + const DrawOptions &aOptions = DrawOptions()); 1.78 + 1.79 + 1.80 + virtual void CopySurface(SourceSurface *aSurface, 1.81 + const IntRect &aSourceRect, 1.82 + const IntPoint &aDestination); 1.83 + 1.84 + virtual void FillRect(const Rect &aRect, 1.85 + const Pattern &aPattern, 1.86 + const DrawOptions &aOptions = DrawOptions()); 1.87 + virtual void StrokeRect(const Rect &aRect, 1.88 + const Pattern &aPattern, 1.89 + const StrokeOptions &aStrokeOptions = StrokeOptions(), 1.90 + const DrawOptions &aOptions = DrawOptions()); 1.91 + virtual void StrokeLine(const Point &aStart, 1.92 + const Point &aEnd, 1.93 + const Pattern &aPattern, 1.94 + const StrokeOptions &aStrokeOptions = StrokeOptions(), 1.95 + const DrawOptions &aOptions = DrawOptions()); 1.96 + virtual void Stroke(const Path *aPath, 1.97 + const Pattern &aPattern, 1.98 + const StrokeOptions &aStrokeOptions = StrokeOptions(), 1.99 + const DrawOptions &aOptions = DrawOptions()); 1.100 + virtual void Fill(const Path *aPath, 1.101 + const Pattern &aPattern, 1.102 + const DrawOptions &aOptions = DrawOptions()); 1.103 + virtual void FillGlyphs(ScaledFont *aFont, 1.104 + const GlyphBuffer &aBuffer, 1.105 + const Pattern &aPattern, 1.106 + const DrawOptions &aOptions = DrawOptions(), 1.107 + const GlyphRenderingOptions *aRenderingOptions = nullptr); 1.108 + virtual void Mask(const Pattern &aSource, 1.109 + const Pattern &aMask, 1.110 + const DrawOptions &aOptions = DrawOptions()); 1.111 + virtual void PushClip(const Path *aPath); 1.112 + virtual void PushClipRect(const Rect &aRect); 1.113 + virtual void PopClip(); 1.114 + 1.115 + virtual TemporaryRef<SourceSurface> CreateSourceSurfaceFromData(unsigned char *aData, 1.116 + const IntSize &aSize, 1.117 + int32_t aStride, 1.118 + SurfaceFormat aFormat) const; 1.119 + virtual TemporaryRef<SourceSurface> OptimizeSourceSurface(SourceSurface *aSurface) const; 1.120 + 1.121 + virtual TemporaryRef<SourceSurface> 1.122 + CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const; 1.123 + 1.124 + virtual TemporaryRef<DrawTarget> 1.125 + CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const; 1.126 + 1.127 + virtual TemporaryRef<PathBuilder> CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const; 1.128 + 1.129 + virtual TemporaryRef<GradientStops> 1.130 + CreateGradientStops(GradientStop *aStops, 1.131 + uint32_t aNumStops, 1.132 + ExtendMode aExtendMode = ExtendMode::CLAMP) const; 1.133 + 1.134 + virtual TemporaryRef<FilterNode> CreateFilter(FilterType aType); 1.135 + 1.136 + virtual void *GetNativeSurface(NativeSurfaceType aType); 1.137 + 1.138 + bool Init(const IntSize &aSize, SurfaceFormat aFormat); 1.139 + bool Init(ID3D10Texture2D *aTexture, SurfaceFormat aFormat); 1.140 + bool InitD3D10Data(); 1.141 + uint32_t GetByteSize() const; 1.142 + TemporaryRef<ID2D1Layer> GetCachedLayer(); 1.143 + void PopCachedLayer(ID2D1RenderTarget *aRT); 1.144 + 1.145 +#ifdef USE_D2D1_1 1.146 + TemporaryRef<ID2D1Image> GetImageForSurface(SourceSurface *aSurface); 1.147 +#endif 1.148 + 1.149 + static ID2D1Factory *factory(); 1.150 + static void CleanupD2D(); 1.151 + static IDWriteFactory *GetDWriteFactory(); 1.152 + ID2D1RenderTarget *GetRT() { return mRT; } 1.153 + 1.154 + operator std::string() const { 1.155 + std::stringstream stream; 1.156 + stream << "DrawTargetD2D(" << this << ")"; 1.157 + return stream.str(); 1.158 + } 1.159 + 1.160 + static uint64_t mVRAMUsageDT; 1.161 + static uint64_t mVRAMUsageSS; 1.162 + 1.163 +private: 1.164 + TemporaryRef<ID2D1Bitmap> 1.165 + GetBitmapForSurface(SourceSurface *aSurface, 1.166 + Rect &aSource); 1.167 + friend class AutoSaveRestoreClippedOut; 1.168 + friend class SourceSurfaceD2DTarget; 1.169 + 1.170 +#ifdef _MSC_VER 1.171 + typedef stdext::hash_set<DrawTargetD2D*> TargetSet; 1.172 +#else 1.173 + typedef std::unordered_set<DrawTargetD2D*> TargetSet; 1.174 +#endif 1.175 + 1.176 + bool InitD2DRenderTarget(); 1.177 + void PrepareForDrawing(ID2D1RenderTarget *aRT); 1.178 + 1.179 + // This function will mark the surface as changing, and make sure any 1.180 + // copy-on-write snapshots are notified. 1.181 + void MarkChanged(); 1.182 + void FlushTransformToRT() { 1.183 + if (mTransformDirty) { 1.184 + mRT->SetTransform(D2DMatrix(mTransform)); 1.185 + mTransformDirty = false; 1.186 + } 1.187 + } 1.188 + void AddDependencyOnSource(SourceSurfaceD2DTarget* aSource); 1.189 + 1.190 + ID3D10BlendState *GetBlendStateForOperator(CompositionOp aOperator); 1.191 + ID2D1RenderTarget *GetRTForOperation(CompositionOp aOperator, const Pattern &aPattern); 1.192 + void FinalizeRTForOperation(CompositionOp aOperator, const Pattern &aPattern, const Rect &aBounds); void EnsureViews(); 1.193 + void PopAllClips(); 1.194 + void PushClipsToRT(ID2D1RenderTarget *aRT); 1.195 + void PopClipsFromRT(ID2D1RenderTarget *aRT); 1.196 + 1.197 + // This function ensures mCurrentClipMaskTexture contains a texture containing 1.198 + // a mask corresponding with the current DrawTarget clip. See 1.199 + // GetClippedGeometry for a description of aClipBounds. 1.200 + void EnsureClipMaskTexture(IntRect *aClipBounds); 1.201 + 1.202 + bool FillGlyphsManual(ScaledFontDWrite *aFont, 1.203 + const GlyphBuffer &aBuffer, 1.204 + const Color &aColor, 1.205 + IDWriteRenderingParams *aParams, 1.206 + const DrawOptions &aOptions = DrawOptions()); 1.207 + 1.208 + TemporaryRef<ID2D1RenderTarget> CreateRTForTexture(ID3D10Texture2D *aTexture, SurfaceFormat aFormat); 1.209 + 1.210 + // This returns the clipped geometry, in addition it returns aClipBounds which 1.211 + // represents the intersection of all pixel-aligned rectangular clips that 1.212 + // are currently set. The returned clipped geometry must be clipped by these 1.213 + // bounds to correctly reflect the total clip. This is in device space. 1.214 + TemporaryRef<ID2D1Geometry> GetClippedGeometry(IntRect *aClipBounds); 1.215 + 1.216 + bool GetDeviceSpaceClipRect(D2D1_RECT_F& aClipRect, bool& aIsPixelAligned); 1.217 + 1.218 + TemporaryRef<ID2D1Brush> CreateBrushForPattern(const Pattern &aPattern, Float aAlpha = 1.0f); 1.219 + 1.220 + TemporaryRef<ID3D10Texture2D> CreateGradientTexture(const GradientStopsD2D *aStops); 1.221 + TemporaryRef<ID3D10Texture2D> CreateTextureForAnalysis(IDWriteGlyphRunAnalysis *aAnalysis, const IntRect &aBounds); 1.222 + 1.223 + void SetupEffectForRadialGradient(const RadialGradientPattern *aPattern); 1.224 + void SetupStateForRendering(); 1.225 + 1.226 + // Set the scissor rect to a certain IntRects, resets the scissor rect to 1.227 + // surface bounds when nullptr is specified. 1.228 + void SetScissorToRect(IntRect *aRect); 1.229 + 1.230 + void PushD2DLayer(ID2D1RenderTarget *aRT, ID2D1Geometry *aGeometry, ID2D1Layer *aLayer, const D2D1_MATRIX_3X2_F &aTransform); 1.231 + 1.232 + static const uint32_t test = 4; 1.233 + 1.234 + IntSize mSize; 1.235 + 1.236 + RefPtr<ID3D10Device1> mDevice; 1.237 + RefPtr<ID3D10Texture2D> mTexture; 1.238 + RefPtr<ID3D10Texture2D> mCurrentClipMaskTexture; 1.239 + RefPtr<ID2D1Geometry> mCurrentClippedGeometry; 1.240 + // This is only valid if mCurrentClippedGeometry is non-null. And will 1.241 + // only be the intersection of all pixel-aligned retangular clips. This is in 1.242 + // device space. 1.243 + IntRect mCurrentClipBounds; 1.244 + mutable RefPtr<ID2D1RenderTarget> mRT; 1.245 + 1.246 + // We store this to prevent excessive SetTextRenderingParams calls. 1.247 + RefPtr<IDWriteRenderingParams> mTextRenderingParams; 1.248 + 1.249 + // Temporary texture and render target used for supporting alternative operators. 1.250 + RefPtr<ID3D10Texture2D> mTempTexture; 1.251 + RefPtr<ID3D10RenderTargetView> mRTView; 1.252 + RefPtr<ID3D10ShaderResourceView> mSRView; 1.253 + RefPtr<ID2D1RenderTarget> mTempRT; 1.254 + RefPtr<ID3D10RenderTargetView> mTempRTView; 1.255 + 1.256 + // List of pushed clips. 1.257 + struct PushedClip 1.258 + { 1.259 + RefPtr<ID2D1Layer> mLayer; 1.260 + D2D1_RECT_F mBounds; 1.261 + union { 1.262 + // If mPath is non-nullptr, the mTransform member will be used, otherwise 1.263 + // the mIsPixelAligned member is valid. 1.264 + D2D1_MATRIX_3X2_F mTransform; 1.265 + bool mIsPixelAligned; 1.266 + }; 1.267 + RefPtr<PathD2D> mPath; 1.268 + }; 1.269 + std::vector<PushedClip> mPushedClips; 1.270 + 1.271 + // We cache ID2D1Layer objects as it causes D2D to keep around textures that 1.272 + // serve as the temporary surfaces for these operations. As texture creation 1.273 + // is quite expensive this considerably improved performance. 1.274 + // Careful here, RAII will not ensure destruction of the RefPtrs. 1.275 + RefPtr<ID2D1Layer> mCachedLayers[kLayerCacheSize]; 1.276 + uint32_t mCurrentCachedLayer; 1.277 + 1.278 + // The latest snapshot of this surface. This needs to be told when this 1.279 + // target is modified. We keep it alive as a cache. 1.280 + RefPtr<SourceSurfaceD2DTarget> mSnapshot; 1.281 + // A list of targets we need to flush when we're modified. 1.282 + TargetSet mDependentTargets; 1.283 + // A list of targets which have this object in their mDependentTargets set 1.284 + TargetSet mDependingOnTargets; 1.285 + 1.286 + // True of the current clip stack is pushed to the main RT. 1.287 + bool mClipsArePushed; 1.288 + PrivateD3D10DataD2D *mPrivateData; 1.289 + static ID2D1Factory *mFactory; 1.290 + static IDWriteFactory *mDWriteFactory; 1.291 +}; 1.292 + 1.293 +} 1.294 +} 1.295 + 1.296 +#endif /* MOZILLA_GFX_DRAWTARGETD2D_H_ */