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 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
{
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
{
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
) {
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 << ")";
170 static uint32_t GetMaxSurfaceSize() {
171 return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION
;
174 static uint64_t mVRAMUsageDT
;
175 static uint64_t mVRAMUsageSS
;
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.
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
;
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
);
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;
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
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.
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.
279 : mClipsArePushed(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
;
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
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
;
326 } // namespace mozilla
328 #endif /* MOZILLA_GFX_DRAWTARGETD2D_H_ */