Bug 1634272 - Don't use DocumentChannel for about:newtab r=mattwoodrow
[gecko.git] / gfx / 2d / DrawTargetD2D1.h
blobf3f2e0d9e437c9eb2109856343d784e6b73ffeab
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 DeviceColor& aColor,
60 const Point& aOffset, Float aSigma,
61 CompositionOp aOperator) override;
62 virtual void ClearRect(const Rect& aRect) override;
63 virtual void MaskSurface(
64 const Pattern& aSource, SourceSurface* aMask, Point aOffset,
65 const DrawOptions& aOptions = DrawOptions()) override;
67 virtual void CopySurface(SourceSurface* aSurface, const IntRect& aSourceRect,
68 const IntPoint& aDestination) override;
70 virtual void FillRect(const Rect& aRect, const Pattern& aPattern,
71 const DrawOptions& aOptions = DrawOptions()) override;
72 virtual void FillRoundedRect(
73 const RoundedRect& aRect, const Pattern& aPattern,
74 const DrawOptions& aOptions = DrawOptions()) override;
76 virtual void StrokeRect(const Rect& aRect, const Pattern& aPattern,
77 const StrokeOptions& aStrokeOptions = StrokeOptions(),
78 const DrawOptions& aOptions = DrawOptions()) override;
79 virtual void StrokeLine(const Point& aStart, const Point& aEnd,
80 const Pattern& aPattern,
81 const StrokeOptions& aStrokeOptions = StrokeOptions(),
82 const DrawOptions& aOptions = DrawOptions()) override;
83 virtual void Stroke(const Path* aPath, const Pattern& aPattern,
84 const StrokeOptions& aStrokeOptions = StrokeOptions(),
85 const DrawOptions& aOptions = DrawOptions()) override;
86 virtual void Fill(const Path* aPath, const Pattern& aPattern,
87 const DrawOptions& aOptions = DrawOptions()) override;
88 virtual void FillGlyphs(ScaledFont* aFont, const GlyphBuffer& aBuffer,
89 const Pattern& aPattern,
90 const DrawOptions& aOptions = DrawOptions()) override;
91 virtual void Mask(const Pattern& aSource, const Pattern& aMask,
92 const DrawOptions& aOptions = DrawOptions()) override;
93 virtual void PushClip(const Path* aPath) override;
94 virtual void PushClipRect(const Rect& aRect) override;
95 virtual void PushDeviceSpaceClipRects(const IntRect* aRects,
96 uint32_t aCount) override;
98 virtual void PopClip() override;
99 virtual void PushLayer(bool aOpaque, Float aOpacity, SourceSurface* aMask,
100 const Matrix& aMaskTransform,
101 const IntRect& aBounds = IntRect(),
102 bool aCopyBackground = false) override;
103 virtual void PopLayer() override;
105 virtual already_AddRefed<SourceSurface> CreateSourceSurfaceFromData(
106 unsigned char* aData, const IntSize& aSize, int32_t aStride,
107 SurfaceFormat aFormat) const override;
108 virtual already_AddRefed<SourceSurface> OptimizeSourceSurface(
109 SourceSurface* aSurface) const override;
111 virtual already_AddRefed<SourceSurface> CreateSourceSurfaceFromNativeSurface(
112 const NativeSurface& aSurface) const override {
113 return nullptr;
116 virtual already_AddRefed<DrawTarget> CreateSimilarDrawTarget(
117 const IntSize& aSize, SurfaceFormat aFormat) const override;
118 virtual bool CanCreateSimilarDrawTarget(const IntSize& aSize,
119 SurfaceFormat aFormat) const override;
120 virtual RefPtr<DrawTarget> CreateClippedDrawTarget(
121 const Rect& aBounds, SurfaceFormat aFormat) override;
123 virtual already_AddRefed<PathBuilder> CreatePathBuilder(
124 FillRule aFillRule = FillRule::FILL_WINDING) const override;
126 virtual already_AddRefed<GradientStops> CreateGradientStops(
127 GradientStop* aStops, uint32_t aNumStops,
128 ExtendMode aExtendMode = ExtendMode::CLAMP) const override;
130 virtual already_AddRefed<FilterNode> CreateFilter(FilterType aType) override;
132 virtual bool SupportsRegionClipping() const override { return false; }
133 virtual bool IsCurrentGroupOpaque() override {
134 return CurrentLayer().mIsOpaque;
137 virtual void* GetNativeSurface(NativeSurfaceType aType) override {
138 return nullptr;
141 virtual void DetachAllSnapshots() override { MarkChanged(); }
143 bool Init(const IntSize& aSize, SurfaceFormat aFormat);
144 bool Init(ID3D11Texture2D* aTexture, SurfaceFormat aFormat);
145 uint32_t GetByteSize() const;
147 // This function will get an image for a surface, it may adjust the source
148 // transform for any transformation of the resulting image relative to the
149 // oritingal SourceSurface. By default, the surface and its transform are
150 // interpreted in user-space, but may be specified in device-space instead.
151 already_AddRefed<ID2D1Image> GetImageForSurface(
152 SourceSurface* aSurface, Matrix& aSourceTransform, ExtendMode aExtendMode,
153 const IntRect* aSourceRect = nullptr, bool aUserSpace = true);
155 already_AddRefed<ID2D1Image> GetImageForSurface(SourceSurface* aSurface,
156 ExtendMode aExtendMode) {
157 Matrix mat;
158 return GetImageForSurface(aSurface, mat, aExtendMode, nullptr);
161 static RefPtr<ID2D1Factory1> factory();
162 static void CleanupD2D();
164 operator std::string() const {
165 std::stringstream stream;
166 stream << "DrawTargetD2D 1.1 (" << this << ")";
167 return stream.str();
170 static uint32_t GetMaxSurfaceSize() {
171 return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
174 static uint64_t mVRAMUsageDT;
175 static uint64_t mVRAMUsageSS;
177 private:
178 friend class SourceSurfaceD2D1;
180 void FlushInternal(bool aHasDependencyMutex = false);
181 bool EnsureInitialized();
183 typedef std::unordered_set<DrawTargetD2D1*> TargetSet;
185 // This function will mark the surface as changing, and make sure any
186 // copy-on-write snapshots are notified.
187 void MarkChanged();
188 bool ShouldClipTemporarySurfaceDrawing(CompositionOp aOp,
189 const Pattern& aPattern,
190 bool aClipIsComplex);
191 bool PrepareForDrawing(CompositionOp aOp, const Pattern& aPattern);
192 void FinalizeDrawing(CompositionOp aOp, const Pattern& aPattern);
193 void FlushTransformToDC() {
194 if (mTransformDirty) {
195 mDC->SetTransform(D2DMatrix(mTransform));
196 mTransformDirty = false;
199 void AddDependencyOnSource(SourceSurfaceD2D1* aSource);
201 // Must be called with all clips popped and an identity matrix set.
202 already_AddRefed<ID2D1Image> GetImageForLayerContent(
203 bool aShouldPreserveContent = true);
205 ID2D1Image* CurrentTarget() {
206 if (CurrentLayer().mCurrentList) {
207 return CurrentLayer().mCurrentList;
209 return mBitmap;
212 // This returns the clipped geometry, in addition it returns aClipBounds which
213 // represents the intersection of all pixel-aligned rectangular clips that
214 // are currently set. The returned clipped geometry must be clipped by these
215 // bounds to correctly reflect the total clip. This is in device space and
216 // only for clips applied to the -current layer-.
217 already_AddRefed<ID2D1Geometry> GetClippedGeometry(IntRect* aClipBounds);
219 already_AddRefed<ID2D1Geometry> GetInverseClippedGeometry();
221 // This gives the device space clip rect applied to the -current layer-.
222 bool GetDeviceSpaceClipRect(D2D1_RECT_F& aClipRect, bool& aIsPixelAligned);
224 void PopAllClips();
225 void PushAllClips();
226 void PushClipsToDC(ID2D1DeviceContext* aDC, bool aForceIgnoreAlpha = false,
227 const D2D1_RECT_F& aMaxRect = D2D1::InfiniteRect());
228 void PopClipsFromDC(ID2D1DeviceContext* aDC);
230 already_AddRefed<ID2D1Brush> CreateTransparentBlackBrush();
231 already_AddRefed<ID2D1SolidColorBrush> GetSolidColorBrush(
232 const D2D_COLOR_F& aColor);
233 already_AddRefed<ID2D1Brush> CreateBrushForPattern(const Pattern& aPattern,
234 Float aAlpha = 1.0f);
236 void PushClipGeometry(ID2D1Geometry* aGeometry,
237 const D2D1_MATRIX_3X2_F& aTransform,
238 bool aPixelAligned = false);
240 void PushD2DLayer(ID2D1DeviceContext* aDC, ID2D1Geometry* aGeometry,
241 const D2D1_MATRIX_3X2_F& aTransform,
242 bool aPixelAligned = false, bool aForceIgnoreAlpha = false,
243 const D2D1_RECT_F& aLayerRect = D2D1::InfiniteRect());
245 // This function is used to determine if the mDC is still valid; if it is
246 // stale, we should avoid using it to execute any draw commands.
247 bool IsDeviceContextValid() const;
249 IntSize mSize;
251 RefPtr<ID2D1Geometry> mCurrentClippedGeometry;
252 // This is only valid if mCurrentClippedGeometry is non-null. And will
253 // only be the intersection of all pixel-aligned retangular clips. This is in
254 // device space.
255 IntRect mCurrentClipBounds;
256 mutable RefPtr<ID2D1DeviceContext> mDC;
257 RefPtr<ID2D1Bitmap1> mBitmap;
258 RefPtr<ID2D1CommandList> mCommandList;
260 RefPtr<ID2D1SolidColorBrush> mSolidColorBrush;
262 // We store this to prevent excessive SetTextRenderingParams calls.
263 RefPtr<IDWriteRenderingParams> mTextRenderingParams;
265 // List of pushed clips.
266 struct PushedClip {
267 D2D1_RECT_F mBounds;
268 // If mGeometry is non-null, the mTransform member will be used.
269 D2D1_MATRIX_3X2_F mTransform;
270 RefPtr<ID2D1Geometry> mGeometry;
271 // Indicates if mBounds, and when non-null, mGeometry with mTransform
272 // applied, are pixel-aligned.
273 bool mIsPixelAligned;
276 // List of pushed layers.
277 struct PushedLayer {
278 PushedLayer()
279 : mClipsArePushed(false),
280 mIsOpaque(false),
281 mOldPermitSubpixelAA(false) {}
283 std::vector<PushedClip> mPushedClips;
284 RefPtr<ID2D1CommandList> mCurrentList;
285 // True if the current clip stack is pushed to the CurrentTarget().
286 bool mClipsArePushed;
287 bool mIsOpaque;
288 bool mOldPermitSubpixelAA;
290 std::vector<PushedLayer> mPushedLayers;
291 PushedLayer& CurrentLayer() { return mPushedLayers.back(); }
293 // The latest snapshot of this surface. This needs to be told when this
294 // target is modified. We keep it alive as a cache.
295 RefPtr<SourceSurfaceD2D1> mSnapshot;
296 std::shared_ptr<Mutex> mSnapshotLock;
297 // A list of targets we need to flush when we're modified.
298 TargetSet mDependentTargets;
299 // A list of targets which have this object in their mDependentTargets set
300 TargetSet mDependingOnTargets;
302 uint32_t mUsedCommandListsSincePurge;
303 uint32_t mTransformedGlyphsSinceLastPurge;
304 // When a BlendEffect has been drawn to a command list, and that command list
305 // is subsequently used -again- as an input to a blend effect for a command
306 // list, this causes an infinite recursion inside D2D as it tries to resolve
307 // the bounds. If we resolve the current command list before this happens we
308 // can avoid the subsequent hang. (See bug 1293586)
309 uint32_t mComplexBlendsWithListInList;
311 static StaticRefPtr<ID2D1Factory1> mFactory;
312 // This value is uesed to verify if the DrawTarget is created by a stale
313 // device.
314 uint32_t mDeviceSeq;
316 // List of effects we use
317 bool EnsureLuminanceEffect();
318 RefPtr<ID2D1Effect> mLuminanceEffect;
320 enum class InitState { Uninitialized, Success, Failure };
321 InitState mInitState;
322 RefPtr<IDXGISurface> mSurface;
325 } // namespace gfx
326 } // namespace mozilla
328 #endif /* MOZILLA_GFX_DRAWTARGETD2D_H_ */