Bug 1866777 - Disable test_race_cache_with_network.js on windows opt for frequent...
[gecko.git] / gfx / 2d / DrawTargetD2D1.h
blobefe571e5887fcb92495567f28167c3243ced6235
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef MOZILLA_GFX_DRAWTARGETD2D1_H_
8 #define MOZILLA_GFX_DRAWTARGETD2D1_H_
10 #include "2D.h"
11 #include <d3d11.h>
12 #include <d2d1_1.h>
13 #include "PathD2D.h"
14 #include "HelpersD2D.h"
15 #include "mozilla/StaticPtr.h"
17 #include <vector>
18 #include <sstream>
20 #include <unordered_set>
22 struct IDWriteFactory;
24 namespace mozilla {
25 namespace gfx {
27 class SourceSurfaceD2D1;
29 const int32_t kLayerCacheSize1 = 5;
31 class DrawTargetD2D1 : public DrawTarget {
32 public:
33 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawTargetD2D1, override)
34 DrawTargetD2D1();
35 virtual ~DrawTargetD2D1();
37 virtual bool IsValid() const override;
38 virtual DrawTargetType GetType() const override {
39 return DrawTargetType::HARDWARE_RASTER;
41 virtual BackendType GetBackendType() const override {
42 return BackendType::DIRECT2D1_1;
44 virtual already_AddRefed<SourceSurface> Snapshot() override;
45 virtual already_AddRefed<SourceSurface> IntoLuminanceSource(
46 LuminanceType aLuminanceType, float aOpacity) override;
47 virtual IntSize GetSize() const override { return mSize; }
49 virtual void Flush() override;
50 virtual void DrawSurface(SourceSurface* aSurface, const Rect& aDest,
51 const Rect& aSource,
52 const DrawSurfaceOptions& aSurfOptions,
53 const DrawOptions& aOptions) override;
54 virtual void DrawFilter(FilterNode* aNode, const Rect& aSourceRect,
55 const Point& aDestPoint,
56 const DrawOptions& aOptions = DrawOptions()) override;
57 virtual void DrawSurfaceWithShadow(SourceSurface* aSurface,
58 const Point& aDest,
59 const ShadowOptions& aShadow,
60 CompositionOp aOperator) override;
61 virtual void ClearRect(const Rect& aRect) override;
62 virtual void MaskSurface(
63 const Pattern& aSource, SourceSurface* aMask, Point aOffset,
64 const DrawOptions& aOptions = DrawOptions()) override;
66 virtual void CopySurface(SourceSurface* aSurface, const IntRect& aSourceRect,
67 const IntPoint& aDestination) override;
69 virtual void FillRect(const Rect& aRect, const Pattern& aPattern,
70 const DrawOptions& aOptions = DrawOptions()) override;
71 virtual void FillRoundedRect(
72 const RoundedRect& aRect, const Pattern& aPattern,
73 const DrawOptions& aOptions = DrawOptions()) override;
75 virtual void StrokeRect(const Rect& aRect, const Pattern& aPattern,
76 const StrokeOptions& aStrokeOptions = StrokeOptions(),
77 const DrawOptions& aOptions = DrawOptions()) override;
78 virtual void StrokeLine(const Point& aStart, const Point& aEnd,
79 const Pattern& aPattern,
80 const StrokeOptions& aStrokeOptions = StrokeOptions(),
81 const DrawOptions& aOptions = DrawOptions()) override;
82 virtual void StrokeCircle(
83 const Point& aOrigin, float radius, const Pattern& aPattern,
84 const StrokeOptions& aStrokeOptions = StrokeOptions(),
85 const DrawOptions& aOptions = DrawOptions()) override;
86 virtual void Stroke(const Path* aPath, const Pattern& aPattern,
87 const StrokeOptions& aStrokeOptions = StrokeOptions(),
88 const DrawOptions& aOptions = DrawOptions()) override;
89 virtual void Fill(const Path* aPath, const Pattern& aPattern,
90 const DrawOptions& aOptions = DrawOptions()) override;
91 virtual void FillCircle(const Point& aOrigin, float radius,
92 const Pattern& aPattern,
93 const DrawOptions& aOptions = DrawOptions()) override;
94 virtual void FillGlyphs(ScaledFont* aFont, const GlyphBuffer& aBuffer,
95 const Pattern& aPattern,
96 const DrawOptions& aOptions = DrawOptions()) override;
97 virtual void Mask(const Pattern& aSource, const Pattern& aMask,
98 const DrawOptions& aOptions = DrawOptions()) override;
99 virtual void PushClip(const Path* aPath) override;
100 virtual void PushClipRect(const Rect& aRect) override;
101 virtual void PushDeviceSpaceClipRects(const IntRect* aRects,
102 uint32_t aCount) override;
104 virtual void PopClip() override;
105 virtual bool RemoveAllClips() override;
107 virtual void PushLayer(bool aOpaque, Float aOpacity, SourceSurface* aMask,
108 const Matrix& aMaskTransform,
109 const IntRect& aBounds = IntRect(),
110 bool aCopyBackground = false) override;
111 virtual void PopLayer() override;
113 virtual already_AddRefed<SourceSurface> CreateSourceSurfaceFromData(
114 unsigned char* aData, const IntSize& aSize, int32_t aStride,
115 SurfaceFormat aFormat) const override;
116 virtual already_AddRefed<SourceSurface> OptimizeSourceSurface(
117 SourceSurface* aSurface) const override;
119 virtual already_AddRefed<SourceSurface> CreateSourceSurfaceFromNativeSurface(
120 const NativeSurface& aSurface) const override {
121 return nullptr;
124 virtual already_AddRefed<DrawTarget> CreateSimilarDrawTarget(
125 const IntSize& aSize, SurfaceFormat aFormat) const override;
126 virtual bool CanCreateSimilarDrawTarget(const IntSize& aSize,
127 SurfaceFormat aFormat) const override;
128 virtual RefPtr<DrawTarget> CreateClippedDrawTarget(
129 const Rect& aBounds, SurfaceFormat aFormat) override;
131 virtual already_AddRefed<PathBuilder> CreatePathBuilder(
132 FillRule aFillRule = FillRule::FILL_WINDING) const override {
133 return PathBuilderD2D::Create(aFillRule);
136 virtual already_AddRefed<GradientStops> CreateGradientStops(
137 GradientStop* aStops, uint32_t aNumStops,
138 ExtendMode aExtendMode = ExtendMode::CLAMP) const override;
140 virtual already_AddRefed<FilterNode> CreateFilter(FilterType aType) override;
142 virtual bool SupportsRegionClipping() const override { return false; }
143 virtual bool IsCurrentGroupOpaque() override {
144 return CurrentLayer().mIsOpaque;
147 virtual void* GetNativeSurface(NativeSurfaceType aType) override {
148 return nullptr;
151 virtual void DetachAllSnapshots() override { MarkChanged(); }
153 bool Init(const IntSize& aSize, SurfaceFormat aFormat);
154 bool Init(ID3D11Texture2D* aTexture, SurfaceFormat aFormat);
155 uint32_t GetByteSize() const;
157 // This function will get an image for a surface, it may adjust the source
158 // transform for any transformation of the resulting image relative to the
159 // oritingal SourceSurface. By default, the surface and its transform are
160 // interpreted in user-space, but may be specified in device-space instead.
161 already_AddRefed<ID2D1Image> GetImageForSurface(
162 SourceSurface* aSurface, Matrix& aSourceTransform, ExtendMode aExtendMode,
163 const IntRect* aSourceRect = nullptr, bool aUserSpace = true);
165 already_AddRefed<ID2D1Image> GetImageForSurface(SourceSurface* aSurface,
166 ExtendMode aExtendMode) {
167 Matrix mat;
168 return GetImageForSurface(aSurface, mat, aExtendMode, nullptr);
171 static RefPtr<ID2D1Factory1> factory();
172 static void CleanupD2D();
174 operator std::string() const {
175 std::stringstream stream;
176 stream << "DrawTargetD2D 1.1 (" << this << ")";
177 return stream.str();
180 static uint32_t GetMaxSurfaceSize() {
181 return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
184 static uint64_t mVRAMUsageDT;
185 static uint64_t mVRAMUsageSS;
187 private:
188 friend class SourceSurfaceD2D1;
190 void FlushInternal(bool aHasDependencyMutex = false);
191 bool EnsureInitialized();
193 typedef std::unordered_set<DrawTargetD2D1*> TargetSet;
195 // This function will mark the surface as changing, and make sure any
196 // copy-on-write snapshots are notified.
197 void MarkChanged();
198 bool ShouldClipTemporarySurfaceDrawing(CompositionOp aOp,
199 const Pattern& aPattern,
200 bool aClipIsComplex);
201 bool PrepareForDrawing(CompositionOp aOp, const Pattern& aPattern);
202 void FinalizeDrawing(CompositionOp aOp, const Pattern& aPattern);
203 bool MaybeClearRect(CompositionOp aOp, const Rect& aBounds);
204 void FlushTransformToDC() {
205 if (mTransformDirty) {
206 mDC->SetTransform(D2DMatrix(mTransform));
207 mTransformDirty = false;
210 void AddDependencyOnSource(SourceSurfaceD2D1* aSource);
212 // Must be called with all clips popped and an identity matrix set.
213 already_AddRefed<ID2D1Image> GetImageForLayerContent(
214 const IntRect* aBounds = nullptr, bool aShouldPreserveContent = true);
216 ID2D1Image* CurrentTarget() {
217 if (CurrentLayer().mCurrentList) {
218 return CurrentLayer().mCurrentList;
220 return mBitmap;
223 // This returns the clipped geometry, in addition it returns aClipBounds which
224 // represents the intersection of all pixel-aligned rectangular clips that
225 // are currently set. The returned clipped geometry must be clipped by these
226 // bounds to correctly reflect the total clip. This is in device space and
227 // only for clips applied to the -current layer-.
228 already_AddRefed<ID2D1Geometry> GetClippedGeometry(IntRect* aClipBounds);
230 already_AddRefed<ID2D1Geometry> GetInverseClippedGeometry();
232 // This gives the device space clip rect applied to the -current layer-.
233 bool GetDeviceSpaceClipRect(D2D1_RECT_F& aClipRect, bool& aIsPixelAligned);
235 void PopAllClips();
236 void PushAllClips();
237 void PushClipsToDC(ID2D1DeviceContext* aDC, bool aForceIgnoreAlpha = false,
238 const D2D1_RECT_F& aMaxRect = D2D1::InfiniteRect());
239 void PopClipsFromDC(ID2D1DeviceContext* aDC);
241 already_AddRefed<ID2D1Brush> CreateTransparentBlackBrush();
242 already_AddRefed<ID2D1SolidColorBrush> GetSolidColorBrush(
243 const D2D_COLOR_F& aColor);
244 already_AddRefed<ID2D1Brush> CreateBrushForPattern(
245 const Pattern& aPattern, const DrawOptions& aOptions);
247 void PushClipGeometry(ID2D1Geometry* aGeometry,
248 const D2D1_MATRIX_3X2_F& aTransform,
249 bool aPixelAligned = false);
251 void PushD2DLayer(ID2D1DeviceContext* aDC, ID2D1Geometry* aGeometry,
252 const D2D1_MATRIX_3X2_F& aTransform,
253 bool aPixelAligned = false, bool aForceIgnoreAlpha = false,
254 const D2D1_RECT_F& aLayerRect = D2D1::InfiniteRect());
256 // This function is used to determine if the mDC is still valid; if it is
257 // stale, we should avoid using it to execute any draw commands.
258 bool IsDeviceContextValid() const;
260 IntSize mSize;
262 RefPtr<ID2D1Geometry> mCurrentClippedGeometry;
263 // This is only valid if mCurrentClippedGeometry is non-null. And will
264 // only be the intersection of all pixel-aligned retangular clips. This is in
265 // device space.
266 IntRect mCurrentClipBounds;
267 mutable RefPtr<ID2D1DeviceContext> mDC;
268 RefPtr<ID2D1Bitmap1> mBitmap;
269 RefPtr<ID2D1CommandList> mCommandList;
271 RefPtr<ID2D1SolidColorBrush> mSolidColorBrush;
273 // We store this to prevent excessive SetTextRenderingParams calls.
274 RefPtr<IDWriteRenderingParams> mTextRenderingParams;
276 // List of pushed clips.
277 struct PushedClip {
278 D2D1_RECT_F mBounds;
279 // If mGeometry is non-null, the mTransform member will be used.
280 D2D1_MATRIX_3X2_F mTransform;
281 RefPtr<ID2D1Geometry> mGeometry;
282 // Indicates if mBounds, and when non-null, mGeometry with mTransform
283 // applied, are pixel-aligned.
284 bool mIsPixelAligned;
287 // List of pushed layers.
288 struct PushedLayer {
289 PushedLayer()
290 : mClipsArePushed(false),
291 mIsOpaque(false),
292 mOldPermitSubpixelAA(false) {}
294 std::vector<PushedClip> mPushedClips;
295 RefPtr<ID2D1CommandList> mCurrentList;
296 // True if the current clip stack is pushed to the CurrentTarget().
297 bool mClipsArePushed;
298 bool mIsOpaque;
299 bool mOldPermitSubpixelAA;
301 std::vector<PushedLayer> mPushedLayers;
302 PushedLayer& CurrentLayer() { return mPushedLayers.back(); }
304 // The latest snapshot of this surface. This needs to be told when this
305 // target is modified. We keep it alive as a cache.
306 RefPtr<SourceSurfaceD2D1> mSnapshot;
307 std::shared_ptr<Mutex> mSnapshotLock;
308 // A list of targets we need to flush when we're modified.
309 TargetSet mDependentTargets;
310 // A list of targets which have this object in their mDependentTargets set
311 TargetSet mDependingOnTargets;
313 uint32_t mUsedCommandListsSincePurge;
314 uint32_t mTransformedGlyphsSinceLastPurge;
315 // When a BlendEffect has been drawn to a command list, and that command list
316 // is subsequently used -again- as an input to a blend effect for a command
317 // list, this causes an infinite recursion inside D2D as it tries to resolve
318 // the bounds. If we resolve the current command list before this happens we
319 // can avoid the subsequent hang. (See bug 1293586)
320 uint32_t mComplexBlendsWithListInList;
322 static StaticRefPtr<ID2D1Factory1> mFactory;
323 // This value is uesed to verify if the DrawTarget is created by a stale
324 // device.
325 uint32_t mDeviceSeq;
327 // List of effects we use
328 bool EnsureLuminanceEffect();
329 RefPtr<ID2D1Effect> mLuminanceEffect;
331 enum class InitState { Uninitialized, Success, Failure };
332 InitState mInitState;
333 RefPtr<IDXGISurface> mSurface;
336 } // namespace gfx
337 } // namespace mozilla
339 #endif /* MOZILLA_GFX_DRAWTARGETD2D_H_ */