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_
14 #include "HelpersD2D.h"
15 #include "mozilla/StaticPtr.h"
20 #include <unordered_set>
22 struct IDWriteFactory
;
27 class SourceSurfaceD2D1
;
29 const int32_t kLayerCacheSize1
= 5;
31 class DrawTargetD2D1
: public DrawTarget
{
33 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawTargetD2D1
, override
)
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
,
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
,
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
{
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
{
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
) {
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 << ")";
180 static uint32_t GetMaxSurfaceSize() {
181 return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION
;
184 static uint64_t mVRAMUsageDT
;
185 static uint64_t mVRAMUsageSS
;
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.
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
;
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
);
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;
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
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.
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.
290 : mClipsArePushed(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
;
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
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
;
337 } // namespace mozilla
339 #endif /* MOZILLA_GFX_DRAWTARGETD2D_H_ */