|
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- |
|
2 * This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #ifndef MOZILLA_GFX_DRAWTARGETD2D_H_ |
|
7 #define MOZILLA_GFX_DRAWTARGETD2D_H_ |
|
8 |
|
9 #include "2D.h" |
|
10 #include "PathD2D.h" |
|
11 #include <d3d10_1.h> |
|
12 #include "HelpersD2D.h" |
|
13 |
|
14 #include <vector> |
|
15 #include <sstream> |
|
16 |
|
17 #ifdef _MSC_VER |
|
18 #include <hash_set> |
|
19 #else |
|
20 #include <unordered_set> |
|
21 #endif |
|
22 |
|
23 struct IDWriteFactory; |
|
24 |
|
25 namespace mozilla { |
|
26 namespace gfx { |
|
27 |
|
28 class SourceSurfaceD2DTarget; |
|
29 class SourceSurfaceD2D; |
|
30 class GradientStopsD2D; |
|
31 class ScaledFontDWrite; |
|
32 |
|
33 const int32_t kLayerCacheSize = 5; |
|
34 |
|
35 struct PrivateD3D10DataD2D |
|
36 { |
|
37 RefPtr<ID3D10Effect> mEffect; |
|
38 RefPtr<ID3D10InputLayout> mInputLayout; |
|
39 RefPtr<ID3D10Buffer> mVB; |
|
40 RefPtr<ID3D10BlendState> mBlendStates[size_t(CompositionOp::OP_COUNT)]; |
|
41 }; |
|
42 |
|
43 class DrawTargetD2D : public DrawTarget |
|
44 { |
|
45 public: |
|
46 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawTargetD2D) |
|
47 DrawTargetD2D(); |
|
48 virtual ~DrawTargetD2D(); |
|
49 |
|
50 virtual BackendType GetType() const { return BackendType::DIRECT2D; } |
|
51 virtual TemporaryRef<SourceSurface> Snapshot(); |
|
52 virtual IntSize GetSize() { return mSize; } |
|
53 |
|
54 virtual void Flush(); |
|
55 virtual void DrawSurface(SourceSurface *aSurface, |
|
56 const Rect &aDest, |
|
57 const Rect &aSource, |
|
58 const DrawSurfaceOptions &aSurfOptions = DrawSurfaceOptions(), |
|
59 const DrawOptions &aOptions = DrawOptions()); |
|
60 virtual void DrawFilter(FilterNode *aNode, |
|
61 const Rect &aSourceRect, |
|
62 const Point &aDestPoint, |
|
63 const DrawOptions &aOptions = DrawOptions()); |
|
64 virtual void DrawSurfaceWithShadow(SourceSurface *aSurface, |
|
65 const Point &aDest, |
|
66 const Color &aColor, |
|
67 const Point &aOffset, |
|
68 Float aSigma, |
|
69 CompositionOp aOperator); |
|
70 virtual void ClearRect(const Rect &aRect); |
|
71 virtual void MaskSurface(const Pattern &aSource, |
|
72 SourceSurface *aMask, |
|
73 Point aOffset, |
|
74 const DrawOptions &aOptions = DrawOptions()); |
|
75 |
|
76 |
|
77 virtual void CopySurface(SourceSurface *aSurface, |
|
78 const IntRect &aSourceRect, |
|
79 const IntPoint &aDestination); |
|
80 |
|
81 virtual void FillRect(const Rect &aRect, |
|
82 const Pattern &aPattern, |
|
83 const DrawOptions &aOptions = DrawOptions()); |
|
84 virtual void StrokeRect(const Rect &aRect, |
|
85 const Pattern &aPattern, |
|
86 const StrokeOptions &aStrokeOptions = StrokeOptions(), |
|
87 const DrawOptions &aOptions = DrawOptions()); |
|
88 virtual void StrokeLine(const Point &aStart, |
|
89 const Point &aEnd, |
|
90 const Pattern &aPattern, |
|
91 const StrokeOptions &aStrokeOptions = StrokeOptions(), |
|
92 const DrawOptions &aOptions = DrawOptions()); |
|
93 virtual void Stroke(const Path *aPath, |
|
94 const Pattern &aPattern, |
|
95 const StrokeOptions &aStrokeOptions = StrokeOptions(), |
|
96 const DrawOptions &aOptions = DrawOptions()); |
|
97 virtual void Fill(const Path *aPath, |
|
98 const Pattern &aPattern, |
|
99 const DrawOptions &aOptions = DrawOptions()); |
|
100 virtual void FillGlyphs(ScaledFont *aFont, |
|
101 const GlyphBuffer &aBuffer, |
|
102 const Pattern &aPattern, |
|
103 const DrawOptions &aOptions = DrawOptions(), |
|
104 const GlyphRenderingOptions *aRenderingOptions = nullptr); |
|
105 virtual void Mask(const Pattern &aSource, |
|
106 const Pattern &aMask, |
|
107 const DrawOptions &aOptions = DrawOptions()); |
|
108 virtual void PushClip(const Path *aPath); |
|
109 virtual void PushClipRect(const Rect &aRect); |
|
110 virtual void PopClip(); |
|
111 |
|
112 virtual TemporaryRef<SourceSurface> CreateSourceSurfaceFromData(unsigned char *aData, |
|
113 const IntSize &aSize, |
|
114 int32_t aStride, |
|
115 SurfaceFormat aFormat) const; |
|
116 virtual TemporaryRef<SourceSurface> OptimizeSourceSurface(SourceSurface *aSurface) const; |
|
117 |
|
118 virtual TemporaryRef<SourceSurface> |
|
119 CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const; |
|
120 |
|
121 virtual TemporaryRef<DrawTarget> |
|
122 CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const; |
|
123 |
|
124 virtual TemporaryRef<PathBuilder> CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const; |
|
125 |
|
126 virtual TemporaryRef<GradientStops> |
|
127 CreateGradientStops(GradientStop *aStops, |
|
128 uint32_t aNumStops, |
|
129 ExtendMode aExtendMode = ExtendMode::CLAMP) const; |
|
130 |
|
131 virtual TemporaryRef<FilterNode> CreateFilter(FilterType aType); |
|
132 |
|
133 virtual void *GetNativeSurface(NativeSurfaceType aType); |
|
134 |
|
135 bool Init(const IntSize &aSize, SurfaceFormat aFormat); |
|
136 bool Init(ID3D10Texture2D *aTexture, SurfaceFormat aFormat); |
|
137 bool InitD3D10Data(); |
|
138 uint32_t GetByteSize() const; |
|
139 TemporaryRef<ID2D1Layer> GetCachedLayer(); |
|
140 void PopCachedLayer(ID2D1RenderTarget *aRT); |
|
141 |
|
142 #ifdef USE_D2D1_1 |
|
143 TemporaryRef<ID2D1Image> GetImageForSurface(SourceSurface *aSurface); |
|
144 #endif |
|
145 |
|
146 static ID2D1Factory *factory(); |
|
147 static void CleanupD2D(); |
|
148 static IDWriteFactory *GetDWriteFactory(); |
|
149 ID2D1RenderTarget *GetRT() { return mRT; } |
|
150 |
|
151 operator std::string() const { |
|
152 std::stringstream stream; |
|
153 stream << "DrawTargetD2D(" << this << ")"; |
|
154 return stream.str(); |
|
155 } |
|
156 |
|
157 static uint64_t mVRAMUsageDT; |
|
158 static uint64_t mVRAMUsageSS; |
|
159 |
|
160 private: |
|
161 TemporaryRef<ID2D1Bitmap> |
|
162 GetBitmapForSurface(SourceSurface *aSurface, |
|
163 Rect &aSource); |
|
164 friend class AutoSaveRestoreClippedOut; |
|
165 friend class SourceSurfaceD2DTarget; |
|
166 |
|
167 #ifdef _MSC_VER |
|
168 typedef stdext::hash_set<DrawTargetD2D*> TargetSet; |
|
169 #else |
|
170 typedef std::unordered_set<DrawTargetD2D*> TargetSet; |
|
171 #endif |
|
172 |
|
173 bool InitD2DRenderTarget(); |
|
174 void PrepareForDrawing(ID2D1RenderTarget *aRT); |
|
175 |
|
176 // This function will mark the surface as changing, and make sure any |
|
177 // copy-on-write snapshots are notified. |
|
178 void MarkChanged(); |
|
179 void FlushTransformToRT() { |
|
180 if (mTransformDirty) { |
|
181 mRT->SetTransform(D2DMatrix(mTransform)); |
|
182 mTransformDirty = false; |
|
183 } |
|
184 } |
|
185 void AddDependencyOnSource(SourceSurfaceD2DTarget* aSource); |
|
186 |
|
187 ID3D10BlendState *GetBlendStateForOperator(CompositionOp aOperator); |
|
188 ID2D1RenderTarget *GetRTForOperation(CompositionOp aOperator, const Pattern &aPattern); |
|
189 void FinalizeRTForOperation(CompositionOp aOperator, const Pattern &aPattern, const Rect &aBounds); void EnsureViews(); |
|
190 void PopAllClips(); |
|
191 void PushClipsToRT(ID2D1RenderTarget *aRT); |
|
192 void PopClipsFromRT(ID2D1RenderTarget *aRT); |
|
193 |
|
194 // This function ensures mCurrentClipMaskTexture contains a texture containing |
|
195 // a mask corresponding with the current DrawTarget clip. See |
|
196 // GetClippedGeometry for a description of aClipBounds. |
|
197 void EnsureClipMaskTexture(IntRect *aClipBounds); |
|
198 |
|
199 bool FillGlyphsManual(ScaledFontDWrite *aFont, |
|
200 const GlyphBuffer &aBuffer, |
|
201 const Color &aColor, |
|
202 IDWriteRenderingParams *aParams, |
|
203 const DrawOptions &aOptions = DrawOptions()); |
|
204 |
|
205 TemporaryRef<ID2D1RenderTarget> CreateRTForTexture(ID3D10Texture2D *aTexture, SurfaceFormat aFormat); |
|
206 |
|
207 // This returns the clipped geometry, in addition it returns aClipBounds which |
|
208 // represents the intersection of all pixel-aligned rectangular clips that |
|
209 // are currently set. The returned clipped geometry must be clipped by these |
|
210 // bounds to correctly reflect the total clip. This is in device space. |
|
211 TemporaryRef<ID2D1Geometry> GetClippedGeometry(IntRect *aClipBounds); |
|
212 |
|
213 bool GetDeviceSpaceClipRect(D2D1_RECT_F& aClipRect, bool& aIsPixelAligned); |
|
214 |
|
215 TemporaryRef<ID2D1Brush> CreateBrushForPattern(const Pattern &aPattern, Float aAlpha = 1.0f); |
|
216 |
|
217 TemporaryRef<ID3D10Texture2D> CreateGradientTexture(const GradientStopsD2D *aStops); |
|
218 TemporaryRef<ID3D10Texture2D> CreateTextureForAnalysis(IDWriteGlyphRunAnalysis *aAnalysis, const IntRect &aBounds); |
|
219 |
|
220 void SetupEffectForRadialGradient(const RadialGradientPattern *aPattern); |
|
221 void SetupStateForRendering(); |
|
222 |
|
223 // Set the scissor rect to a certain IntRects, resets the scissor rect to |
|
224 // surface bounds when nullptr is specified. |
|
225 void SetScissorToRect(IntRect *aRect); |
|
226 |
|
227 void PushD2DLayer(ID2D1RenderTarget *aRT, ID2D1Geometry *aGeometry, ID2D1Layer *aLayer, const D2D1_MATRIX_3X2_F &aTransform); |
|
228 |
|
229 static const uint32_t test = 4; |
|
230 |
|
231 IntSize mSize; |
|
232 |
|
233 RefPtr<ID3D10Device1> mDevice; |
|
234 RefPtr<ID3D10Texture2D> mTexture; |
|
235 RefPtr<ID3D10Texture2D> mCurrentClipMaskTexture; |
|
236 RefPtr<ID2D1Geometry> mCurrentClippedGeometry; |
|
237 // This is only valid if mCurrentClippedGeometry is non-null. And will |
|
238 // only be the intersection of all pixel-aligned retangular clips. This is in |
|
239 // device space. |
|
240 IntRect mCurrentClipBounds; |
|
241 mutable RefPtr<ID2D1RenderTarget> mRT; |
|
242 |
|
243 // We store this to prevent excessive SetTextRenderingParams calls. |
|
244 RefPtr<IDWriteRenderingParams> mTextRenderingParams; |
|
245 |
|
246 // Temporary texture and render target used for supporting alternative operators. |
|
247 RefPtr<ID3D10Texture2D> mTempTexture; |
|
248 RefPtr<ID3D10RenderTargetView> mRTView; |
|
249 RefPtr<ID3D10ShaderResourceView> mSRView; |
|
250 RefPtr<ID2D1RenderTarget> mTempRT; |
|
251 RefPtr<ID3D10RenderTargetView> mTempRTView; |
|
252 |
|
253 // List of pushed clips. |
|
254 struct PushedClip |
|
255 { |
|
256 RefPtr<ID2D1Layer> mLayer; |
|
257 D2D1_RECT_F mBounds; |
|
258 union { |
|
259 // If mPath is non-nullptr, the mTransform member will be used, otherwise |
|
260 // the mIsPixelAligned member is valid. |
|
261 D2D1_MATRIX_3X2_F mTransform; |
|
262 bool mIsPixelAligned; |
|
263 }; |
|
264 RefPtr<PathD2D> mPath; |
|
265 }; |
|
266 std::vector<PushedClip> mPushedClips; |
|
267 |
|
268 // We cache ID2D1Layer objects as it causes D2D to keep around textures that |
|
269 // serve as the temporary surfaces for these operations. As texture creation |
|
270 // is quite expensive this considerably improved performance. |
|
271 // Careful here, RAII will not ensure destruction of the RefPtrs. |
|
272 RefPtr<ID2D1Layer> mCachedLayers[kLayerCacheSize]; |
|
273 uint32_t mCurrentCachedLayer; |
|
274 |
|
275 // The latest snapshot of this surface. This needs to be told when this |
|
276 // target is modified. We keep it alive as a cache. |
|
277 RefPtr<SourceSurfaceD2DTarget> mSnapshot; |
|
278 // A list of targets we need to flush when we're modified. |
|
279 TargetSet mDependentTargets; |
|
280 // A list of targets which have this object in their mDependentTargets set |
|
281 TargetSet mDependingOnTargets; |
|
282 |
|
283 // True of the current clip stack is pushed to the main RT. |
|
284 bool mClipsArePushed; |
|
285 PrivateD3D10DataD2D *mPrivateData; |
|
286 static ID2D1Factory *mFactory; |
|
287 static IDWriteFactory *mDWriteFactory; |
|
288 }; |
|
289 |
|
290 } |
|
291 } |
|
292 |
|
293 #endif /* MOZILLA_GFX_DRAWTARGETD2D_H_ */ |