/src/mozilla-central/gfx/layers/composite/LayerManagerComposite.h
Line | Count | Source (jump to first uncovered line) |
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/. */ |
6 | | |
7 | | #ifndef GFX_LayerManagerComposite_H |
8 | | #define GFX_LayerManagerComposite_H |
9 | | |
10 | | #include <stdint.h> // for int32_t, uint32_t |
11 | | #include "CompositableHost.h" // for CompositableHost, ImageCompositeNotificationInfo |
12 | | #include "GLDefs.h" // for GLenum |
13 | | #include "Layers.h" |
14 | | #include "Units.h" // for ParentLayerIntRect |
15 | | #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc |
16 | | #include "mozilla/Attributes.h" // for override |
17 | | #include "mozilla/RefPtr.h" // for RefPtr, already_AddRefed |
18 | | #include "mozilla/gfx/2D.h" |
19 | | #include "mozilla/gfx/Point.h" // for IntSize |
20 | | #include "mozilla/gfx/Rect.h" // for Rect |
21 | | #include "mozilla/gfx/Types.h" // for SurfaceFormat |
22 | | #include "mozilla/layers/CompositorTypes.h" |
23 | | #include "mozilla/layers/Effects.h" // for EffectChain |
24 | | #include "mozilla/layers/LayersMessages.h" |
25 | | #include "mozilla/layers/LayersTypes.h" // for LayersBackend, etc |
26 | | #include "mozilla/Maybe.h" // for Maybe |
27 | | #include "mozilla/RefPtr.h" |
28 | | #include "mozilla/UniquePtr.h" |
29 | | #include "nsAString.h" |
30 | | #include "mozilla/RefPtr.h" // for nsRefPtr |
31 | | #include "nsCOMPtr.h" // for already_AddRefed |
32 | | #include "nsDebug.h" // for NS_ASSERTION |
33 | | #include "nsISupportsImpl.h" // for Layer::AddRef, etc |
34 | | #include "nsRect.h" // for mozilla::gfx::IntRect |
35 | | #include "nsRegion.h" // for nsIntRegion |
36 | | #include "nscore.h" // for nsAString, etc |
37 | | #include "LayerTreeInvalidation.h" |
38 | | #include "mozilla/layers/CompositorScreenshotGrabber.h" |
39 | | |
40 | | class gfxContext; |
41 | | |
42 | | #ifdef XP_WIN |
43 | | #include <windows.h> |
44 | | #endif |
45 | | |
46 | | namespace mozilla { |
47 | | namespace gfx { |
48 | | class DrawTarget; |
49 | | } // namespace gfx |
50 | | |
51 | | namespace layers { |
52 | | |
53 | | class CanvasLayerComposite; |
54 | | class ColorLayerComposite; |
55 | | class Compositor; |
56 | | class ContainerLayerComposite; |
57 | | class Diagnostics; |
58 | | struct EffectChain; |
59 | | class ImageLayer; |
60 | | class ImageLayerComposite; |
61 | | class LayerComposite; |
62 | | class RefLayerComposite; |
63 | | class PaintedLayerComposite; |
64 | | class TextRenderer; |
65 | | class CompositingRenderTarget; |
66 | | struct FPSState; |
67 | | class PaintCounter; |
68 | | class LayerMLGPU; |
69 | | class LayerManagerMLGPU; |
70 | | class UiCompositorControllerParent; |
71 | | |
72 | | static const int kVisualWarningDuration = 150; // ms |
73 | | |
74 | | // An implementation of LayerManager that acts as a pair with ClientLayerManager |
75 | | // and is mirrored across IPDL. This gets managed/updated by LayerTransactionParent. |
76 | | class HostLayerManager : public LayerManager |
77 | | { |
78 | | public: |
79 | | HostLayerManager(); |
80 | | ~HostLayerManager(); |
81 | | |
82 | | virtual bool BeginTransactionWithTarget(gfxContext* aTarget) override |
83 | 0 | { |
84 | 0 | MOZ_CRASH("GFX: Use BeginTransactionWithDrawTarget"); |
85 | 0 | } |
86 | | |
87 | | virtual bool EndEmptyTransaction(EndTransactionFlags aFlags = END_DEFAULT) override |
88 | 0 | { |
89 | 0 | MOZ_CRASH("GFX: Use EndTransaction(aTimeStamp)"); |
90 | 0 | return false; |
91 | 0 | } |
92 | | |
93 | | virtual void EndTransaction(DrawPaintedLayerCallback aCallback, |
94 | | void* aCallbackData, |
95 | | EndTransactionFlags aFlags = END_DEFAULT) override |
96 | 0 | { |
97 | 0 | MOZ_CRASH("GFX: Use EndTransaction(aTimeStamp)"); |
98 | 0 | } |
99 | | |
100 | | virtual int32_t GetMaxTextureSize() const override |
101 | 0 | { |
102 | 0 | MOZ_CRASH("GFX: Call on compositor, not LayerManagerComposite"); |
103 | 0 | } |
104 | | |
105 | | virtual void GetBackendName(nsAString& name) override |
106 | 0 | { |
107 | 0 | MOZ_CRASH("GFX: Shouldn't be called for composited layer manager"); |
108 | 0 | } |
109 | | |
110 | | virtual void ForcePresent() = 0; |
111 | | virtual void AddInvalidRegion(const nsIntRegion& aRegion) = 0; |
112 | | |
113 | 0 | virtual void NotifyShadowTreeTransaction() {} |
114 | | virtual void BeginTransactionWithDrawTarget(gfx::DrawTarget* aTarget, |
115 | | const gfx::IntRect& aRect) = 0; |
116 | | virtual Compositor* GetCompositor() const = 0; |
117 | | virtual TextureSourceProvider* GetTextureSourceProvider() const = 0; |
118 | | virtual void EndTransaction(const TimeStamp& aTimeStamp, |
119 | | EndTransactionFlags aFlags = END_DEFAULT) = 0; |
120 | 0 | virtual void UpdateRenderBounds(const gfx::IntRect& aRect) {} |
121 | 0 | virtual void SetDiagnosticTypes(DiagnosticTypes aDiagnostics) {} |
122 | | virtual void InvalidateAll() = 0; |
123 | | |
124 | 0 | virtual HostLayerManager* AsHostLayerManager() override { |
125 | 0 | return this; |
126 | 0 | } |
127 | 0 | virtual LayerManagerMLGPU* AsLayerManagerMLGPU() { |
128 | 0 | return nullptr; |
129 | 0 | } |
130 | | |
131 | | void ExtractImageCompositeNotifications(nsTArray<ImageCompositeNotificationInfo>* aNotifications) |
132 | | { |
133 | | aNotifications->AppendElements(std::move(mImageCompositeNotifications)); |
134 | | } |
135 | | |
136 | | void AppendImageCompositeNotification(const ImageCompositeNotificationInfo& aNotification) |
137 | 0 | { |
138 | 0 | // Only send composite notifications when we're drawing to the screen, |
139 | 0 | // because that's what they mean. |
140 | 0 | // Also when we're not drawing to the screen, DidComposite will not be |
141 | 0 | // called to extract and send these notifications, so they might linger |
142 | 0 | // and contain stale ImageContainerParent pointers. |
143 | 0 | if (IsCompositingToScreen()) { |
144 | 0 | mImageCompositeNotifications.AppendElement(aNotification); |
145 | 0 | } |
146 | 0 | } |
147 | | |
148 | | /** |
149 | | * LayerManagerComposite provides sophisticated debug overlays |
150 | | * that can request a next frame. |
151 | | */ |
152 | | bool DebugOverlayWantsNextFrame() { return mDebugOverlayWantsNextFrame; } |
153 | | void SetDebugOverlayWantsNextFrame(bool aVal) |
154 | 0 | { mDebugOverlayWantsNextFrame = aVal; } |
155 | | |
156 | | /** |
157 | | * Add an on frame warning. |
158 | | * @param severity ranges from 0 to 1. It's used to compute the warning color. |
159 | | */ |
160 | | void VisualFrameWarning(float severity) { |
161 | | mozilla::TimeStamp now = TimeStamp::Now(); |
162 | | if (mWarnTime.IsNull() || |
163 | | severity > mWarningLevel || |
164 | | mWarnTime + TimeDuration::FromMilliseconds(kVisualWarningDuration) < now) { |
165 | | mWarnTime = now; |
166 | | mWarningLevel = severity; |
167 | | } |
168 | | } |
169 | | |
170 | | // Indicate that we need to composite even if nothing in our layers has |
171 | | // changed, so that the widget can draw something different in its window |
172 | | // overlay. |
173 | | void SetWindowOverlayChanged() { mWindowOverlayChanged = true; } |
174 | | |
175 | | void SetPaintTime(const TimeDuration& aPaintTime) { mLastPaintTime = aPaintTime; } |
176 | | |
177 | 0 | virtual bool AlwaysScheduleComposite() const { |
178 | 0 | return false; |
179 | 0 | } |
180 | 0 | virtual bool IsCompositingToScreen() const { |
181 | 0 | return false; |
182 | 0 | } |
183 | | |
184 | | void RecordPaintTimes(const PaintTiming& aTiming); |
185 | | void RecordUpdateTime(float aValue); |
186 | | |
187 | 0 | TimeStamp GetCompositionTime() const { |
188 | 0 | return mCompositionTime; |
189 | 0 | } |
190 | 0 | void SetCompositionTime(TimeStamp aTimeStamp) { |
191 | 0 | mCompositionTime = aTimeStamp; |
192 | 0 | if (!mCompositionTime.IsNull() && !mCompositeUntilTime.IsNull() && |
193 | 0 | mCompositionTime >= mCompositeUntilTime) { |
194 | 0 | mCompositeUntilTime = TimeStamp(); |
195 | 0 | } |
196 | 0 | } |
197 | 0 | void CompositeUntil(TimeStamp aTimeStamp) { |
198 | 0 | if (mCompositeUntilTime.IsNull() || |
199 | 0 | mCompositeUntilTime < aTimeStamp) { |
200 | 0 | mCompositeUntilTime = aTimeStamp; |
201 | 0 | } |
202 | 0 | } |
203 | | TimeStamp GetCompositeUntilTime() const { |
204 | | return mCompositeUntilTime; |
205 | | } |
206 | | |
207 | | // We maintaining a global mapping from ID to CompositorBridgeParent for |
208 | | // async compositables. |
209 | | uint64_t GetCompositorBridgeID() const { |
210 | | return mCompositorBridgeID; |
211 | | } |
212 | | void SetCompositorBridgeID(uint64_t aID) { |
213 | | MOZ_ASSERT(mCompositorBridgeID == 0, "The compositor ID must be set only once."); |
214 | | mCompositorBridgeID = aID; |
215 | | } |
216 | | |
217 | | protected: |
218 | | bool mDebugOverlayWantsNextFrame; |
219 | | nsTArray<ImageCompositeNotificationInfo> mImageCompositeNotifications; |
220 | | // Testing property. If hardware composer is supported, this will return |
221 | | // true if the last frame was deemed 'too complicated' to be rendered. |
222 | | float mWarningLevel; |
223 | | mozilla::TimeStamp mWarnTime; |
224 | | UniquePtr<Diagnostics> mDiagnostics; |
225 | | uint64_t mCompositorBridgeID; |
226 | | |
227 | | bool mWindowOverlayChanged; |
228 | | TimeDuration mLastPaintTime; |
229 | | TimeStamp mRenderStartTime; |
230 | | |
231 | | // Render time for the current composition. |
232 | | TimeStamp mCompositionTime; |
233 | | |
234 | | // When nonnull, during rendering, some compositable indicated that it will |
235 | | // change its rendering at this time. In order not to miss it, we composite |
236 | | // on every vsync until this time occurs (this is the latest such time). |
237 | | TimeStamp mCompositeUntilTime; |
238 | | #if defined(MOZ_WIDGET_ANDROID) |
239 | | public: |
240 | | // Used by UiCompositorControllerParent to set itself as the target for the |
241 | | // contents of the frame buffer after a composite. |
242 | | // Implemented in LayerManagerComposite |
243 | | virtual void RequestScreenPixels(UiCompositorControllerParent* aController) {} |
244 | | #endif // defined(MOZ_WIDGET_ANDROID) |
245 | | }; |
246 | | |
247 | | // A layer manager implementation that uses the Compositor API |
248 | | // to render layers. |
249 | | class LayerManagerComposite final : public HostLayerManager |
250 | | { |
251 | | typedef mozilla::gfx::DrawTarget DrawTarget; |
252 | | typedef mozilla::gfx::IntSize IntSize; |
253 | | typedef mozilla::gfx::SurfaceFormat SurfaceFormat; |
254 | | |
255 | | public: |
256 | | explicit LayerManagerComposite(Compositor* aCompositor); |
257 | | ~LayerManagerComposite(); |
258 | | |
259 | | virtual void Destroy() override; |
260 | | |
261 | | /** |
262 | | * Sets the clipping region for this layer manager. This is important on |
263 | | * windows because using OGL we no longer have GDI's native clipping. Therefor |
264 | | * widget must tell us what part of the screen is being invalidated, |
265 | | * and we should clip to this. |
266 | | * |
267 | | * \param aClippingRegion Region to clip to. Setting an empty region |
268 | | * will disable clipping. |
269 | | */ |
270 | | void SetClippingRegion(const nsIntRegion& aClippingRegion) |
271 | | { |
272 | | mClippingRegion = aClippingRegion; |
273 | | } |
274 | | |
275 | | /** |
276 | | * LayerManager implementation. |
277 | | */ |
278 | | virtual LayerManagerComposite* AsLayerManagerComposite() override |
279 | 0 | { |
280 | 0 | return this; |
281 | 0 | } |
282 | | |
283 | | void UpdateRenderBounds(const gfx::IntRect& aRect) override; |
284 | | |
285 | | virtual bool BeginTransaction() override; |
286 | | void BeginTransactionWithDrawTarget(gfx::DrawTarget* aTarget, |
287 | | const gfx::IntRect& aRect) override; |
288 | | void EndTransaction(const TimeStamp& aTimeStamp, |
289 | | EndTransactionFlags aFlags = END_DEFAULT) override; |
290 | | virtual void EndTransaction(DrawPaintedLayerCallback aCallback, |
291 | | void* aCallbackData, |
292 | | EndTransactionFlags aFlags = END_DEFAULT) override |
293 | 0 | { |
294 | 0 | MOZ_CRASH("GFX: Use EndTransaction(aTimeStamp)"); |
295 | 0 | } |
296 | | |
297 | 0 | virtual void SetRoot(Layer* aLayer) override { mRoot = aLayer; } |
298 | | |
299 | | // XXX[nrc]: never called, we should move this logic to ClientLayerManager |
300 | | // (bug 946926). |
301 | | virtual bool CanUseCanvasLayerForSize(const gfx::IntSize &aSize) override; |
302 | | |
303 | | virtual void ClearCachedResources(Layer* aSubtree = nullptr) override; |
304 | | |
305 | | virtual already_AddRefed<PaintedLayer> CreatePaintedLayer() override; |
306 | | virtual already_AddRefed<ContainerLayer> CreateContainerLayer() override; |
307 | | virtual already_AddRefed<ImageLayer> CreateImageLayer() override; |
308 | | virtual already_AddRefed<ColorLayer> CreateColorLayer() override; |
309 | | virtual already_AddRefed<CanvasLayer> CreateCanvasLayer() override; |
310 | | virtual already_AddRefed<RefLayer> CreateRefLayer() override; |
311 | | |
312 | | virtual bool AreComponentAlphaLayersEnabled() override; |
313 | | |
314 | | virtual already_AddRefed<DrawTarget> |
315 | | CreateOptimalMaskDrawTarget(const IntSize &aSize) override; |
316 | | |
317 | 0 | virtual const char* Name() const override { return ""; } |
318 | | virtual bool IsCompositingToScreen() const override; |
319 | | |
320 | | bool AlwaysScheduleComposite() const override; |
321 | | |
322 | | /** |
323 | | * Post-processes layers before composition. This performs the following: |
324 | | * |
325 | | * - Applies occlusion culling. This restricts the shadow visible region |
326 | | * of layers that are covered with opaque content. |
327 | | * |aOpaqueRegion| is the region already known to be covered with opaque |
328 | | * content, in the post-transform coordinate space of aLayer. |
329 | | * |
330 | | * - Recomputes visible regions to account for async transforms. |
331 | | * Each layer accumulates into |aVisibleRegion| its post-transform |
332 | | * (including async transforms) visible region. |
333 | | * |
334 | | * - aRenderTargetClip is the exact clip required for aLayer, in the coordinates |
335 | | * of the nearest render target (the same as GetEffectiveTransform). |
336 | | * |
337 | | * - aClipFromAncestors is the approximate combined clip from all ancestors, in |
338 | | * the coordinate space of our parent, but maybe be an overestimate in the |
339 | | * presence of complex transforms. |
340 | | */ |
341 | | void PostProcessLayers(nsIntRegion& aOpaqueRegion); |
342 | | void PostProcessLayers(Layer* aLayer, |
343 | | nsIntRegion& aOpaqueRegion, |
344 | | LayerIntRegion& aVisibleRegion, |
345 | | const Maybe<RenderTargetIntRect>& aRenderTargetClip, |
346 | | const Maybe<ParentLayerIntRect>& aClipFromAncestors); |
347 | | |
348 | | /** |
349 | | * RAII helper class to add a mask effect with the compositable from aMaskLayer |
350 | | * to the EffectChain aEffect and notify the compositable when we are done. |
351 | | */ |
352 | | class AutoAddMaskEffect |
353 | | { |
354 | | public: |
355 | | AutoAddMaskEffect(Layer* aMaskLayer, |
356 | | EffectChain& aEffect); |
357 | | ~AutoAddMaskEffect(); |
358 | | |
359 | 0 | bool Failed() const { return mFailed; } |
360 | | private: |
361 | | CompositableHost* mCompositable; |
362 | | bool mFailed; |
363 | | }; |
364 | | |
365 | | /** |
366 | | * returns true if PlatformAllocBuffer will return a buffer that supports |
367 | | * direct texturing |
368 | | */ |
369 | | static bool SupportsDirectTexturing(); |
370 | | |
371 | | static void PlatformSyncBeforeReplyUpdate(); |
372 | | |
373 | | void AddInvalidRegion(const nsIntRegion& aRegion) override |
374 | 0 | { |
375 | 0 | mInvalidRegion.Or(mInvalidRegion, aRegion); |
376 | 0 | } |
377 | | |
378 | 0 | Compositor* GetCompositor() const override { |
379 | 0 | return mCompositor; |
380 | 0 | } |
381 | 0 | TextureSourceProvider* GetTextureSourceProvider() const override { |
382 | 0 | return mCompositor; |
383 | 0 | } |
384 | | |
385 | | void NotifyShadowTreeTransaction() override; |
386 | | |
387 | 0 | TextRenderer* GetTextRenderer() { return mTextRenderer; } |
388 | | |
389 | 0 | void UnusedApzTransformWarning() { |
390 | 0 | mUnusedApzTransformWarning = true; |
391 | 0 | } |
392 | 0 | void DisabledApzWarning() { |
393 | 0 | mDisabledApzWarning = true; |
394 | 0 | } |
395 | | |
396 | | bool AsyncPanZoomEnabled() const override; |
397 | | |
398 | | public: |
399 | 0 | virtual TextureFactoryIdentifier GetTextureFactoryIdentifier() override { |
400 | 0 | return mCompositor->GetTextureFactoryIdentifier(); |
401 | 0 | } |
402 | 0 | virtual LayersBackend GetBackendType() override { |
403 | 0 | return mCompositor ? mCompositor->GetBackendType() : LayersBackend::LAYERS_NONE; |
404 | 0 | } |
405 | 0 | virtual void SetDiagnosticTypes(DiagnosticTypes aDiagnostics) override { |
406 | 0 | mCompositor->SetDiagnosticTypes(aDiagnostics); |
407 | 0 | } |
408 | | |
409 | 0 | virtual void InvalidateAll() override { |
410 | 0 | AddInvalidRegion(nsIntRegion(mRenderBounds)); |
411 | 0 | } |
412 | | |
413 | 0 | void ForcePresent() override { mCompositor->ForcePresent(); } |
414 | | |
415 | | private: |
416 | | /** Region we're clipping our current drawing to. */ |
417 | | nsIntRegion mClippingRegion; |
418 | | gfx::IntRect mRenderBounds; |
419 | | |
420 | | /** Current root layer. */ |
421 | | LayerComposite* RootLayer() const; |
422 | | |
423 | | /** |
424 | | * Update the invalid region and render it. |
425 | | */ |
426 | | void UpdateAndRender(); |
427 | | |
428 | | /** |
429 | | * Render the current layer tree to the active target. |
430 | | */ |
431 | | void Render(const nsIntRegion& aInvalidRegion, const nsIntRegion& aOpaqueRegion); |
432 | | #if defined(MOZ_WIDGET_ANDROID) |
433 | | void RenderToPresentationSurface(); |
434 | | // Shifts the content down so the toolbar does not cover it. |
435 | | // Returns the Y shift of the content in screen pixels |
436 | | ScreenCoord GetContentShiftForToolbar(); |
437 | | // Renders the static snapshot after the content has been rendered. |
438 | | void RenderToolbar(); |
439 | | // Used by robocop tests to get a snapshot of the frame buffer. |
440 | | void HandlePixelsTarget(); |
441 | | #endif |
442 | | |
443 | | /** |
444 | | * We need to know our invalid region before we're ready to render. |
445 | | */ |
446 | | void InvalidateDebugOverlay(nsIntRegion& aInvalidRegion, const gfx::IntRect& aBounds); |
447 | | |
448 | | /** |
449 | | * Render debug overlays such as the FPS/FrameCounter above the frame. |
450 | | */ |
451 | | void RenderDebugOverlay(const gfx::IntRect& aBounds); |
452 | | |
453 | | RefPtr<CompositingRenderTarget> PushGroupForLayerEffects(); |
454 | | void PopGroupForLayerEffects(RefPtr<CompositingRenderTarget> aPreviousTarget, |
455 | | gfx::IntRect aClipRect, |
456 | | bool aGrayscaleEffect, |
457 | | bool aInvertEffect, |
458 | | float aContrastEffect); |
459 | | |
460 | | bool mUnusedApzTransformWarning; |
461 | | bool mDisabledApzWarning; |
462 | | RefPtr<Compositor> mCompositor; |
463 | | UniquePtr<LayerProperties> mClonedLayerTreeProperties; |
464 | | |
465 | | /** |
466 | | * Context target, nullptr when drawing directly to our swap chain. |
467 | | */ |
468 | | RefPtr<gfx::DrawTarget> mTarget; |
469 | | gfx::IntRect mTargetBounds; |
470 | | |
471 | | nsIntRegion mInvalidRegion; |
472 | | |
473 | | bool mInTransaction; |
474 | | bool mIsCompositorReady; |
475 | | |
476 | | RefPtr<CompositingRenderTarget> mTwoPassTmpTarget; |
477 | | CompositorScreenshotGrabber mProfilerScreenshotGrabber; |
478 | | RefPtr<TextRenderer> mTextRenderer; |
479 | | |
480 | | #ifdef USE_SKIA |
481 | | /** |
482 | | * Render paint and composite times above the frame. |
483 | | */ |
484 | | void DrawPaintTimes(Compositor* aCompositor); |
485 | | RefPtr<PaintCounter> mPaintCounter; |
486 | | #endif |
487 | | #if defined(MOZ_WIDGET_ANDROID) |
488 | | public: |
489 | | virtual void RequestScreenPixels(UiCompositorControllerParent* aController) override |
490 | | { |
491 | | mScreenPixelsTarget = aController; |
492 | | } |
493 | | private: |
494 | | UiCompositorControllerParent* mScreenPixelsTarget; |
495 | | #endif // defined(MOZ_WIDGET_ANDROID) |
496 | | }; |
497 | | |
498 | | /** |
499 | | * Compositor layers are for use with OMTC on the compositor thread only. There |
500 | | * must be corresponding Client layers on the content thread. For composite |
501 | | * layers, the layer manager only maintains the layer tree. |
502 | | */ |
503 | | class HostLayer |
504 | | { |
505 | | public: |
506 | | explicit HostLayer(HostLayerManager* aManager) |
507 | | : mCompositorManager(aManager) |
508 | | , mShadowOpacity(1.0) |
509 | | , mShadowTransformSetByAnimation(false) |
510 | | , mShadowOpacitySetByAnimation(false) |
511 | 0 | { |
512 | 0 | } |
513 | | |
514 | | virtual void SetLayerManager(HostLayerManager* aManager) |
515 | | { |
516 | | mCompositorManager = aManager; |
517 | | } |
518 | | HostLayerManager* GetLayerManager() const { return mCompositorManager; } |
519 | | |
520 | | |
521 | | virtual ~HostLayer() {} |
522 | | |
523 | | virtual LayerComposite* GetFirstChildComposite() |
524 | | { |
525 | | return nullptr; |
526 | | } |
527 | | |
528 | | virtual Layer* GetLayer() = 0; |
529 | | |
530 | | virtual LayerMLGPU* AsLayerMLGPU() { return nullptr; } |
531 | | |
532 | | virtual bool SetCompositableHost(CompositableHost*) |
533 | | { |
534 | | // We must handle this gracefully, see bug 967824 |
535 | | NS_WARNING("called SetCompositableHost for a layer type not accepting a compositable"); |
536 | | return false; |
537 | | } |
538 | | virtual CompositableHost* GetCompositableHost() = 0; |
539 | | |
540 | | /** |
541 | | * The following methods are |
542 | | * |
543 | | * CONSTRUCTION PHASE ONLY |
544 | | * |
545 | | * They are analogous to the Layer interface. |
546 | | */ |
547 | | void SetShadowVisibleRegion(const LayerIntRegion& aRegion) |
548 | | { |
549 | | mShadowVisibleRegion = aRegion; |
550 | | } |
551 | | void SetShadowVisibleRegion(LayerIntRegion&& aRegion) |
552 | | { |
553 | | mShadowVisibleRegion = std::move(aRegion); |
554 | | } |
555 | | |
556 | | void SetShadowOpacity(float aOpacity) |
557 | 0 | { |
558 | 0 | mShadowOpacity = aOpacity; |
559 | 0 | } |
560 | | void SetShadowOpacitySetByAnimation(bool aSetByAnimation) |
561 | 0 | { |
562 | 0 | mShadowOpacitySetByAnimation = aSetByAnimation; |
563 | 0 | } |
564 | | |
565 | | void SetShadowClipRect(const Maybe<ParentLayerIntRect>& aRect) |
566 | 0 | { |
567 | 0 | mShadowClipRect = aRect; |
568 | 0 | } |
569 | | |
570 | | void SetShadowBaseTransform(const gfx::Matrix4x4& aMatrix) |
571 | 0 | { |
572 | 0 | mShadowTransform = aMatrix; |
573 | 0 | } |
574 | | void SetShadowTransformSetByAnimation(bool aSetByAnimation) |
575 | 0 | { |
576 | 0 | mShadowTransformSetByAnimation = aSetByAnimation; |
577 | 0 | } |
578 | | |
579 | | // These getters can be used anytime. |
580 | | float GetShadowOpacity() { return mShadowOpacity; } |
581 | | const Maybe<ParentLayerIntRect>& GetShadowClipRect() { return mShadowClipRect; } |
582 | | virtual const LayerIntRegion& GetShadowVisibleRegion() { return mShadowVisibleRegion; } |
583 | | const gfx::Matrix4x4& GetShadowBaseTransform() { return mShadowTransform; } |
584 | | gfx::Matrix4x4 GetShadowTransform(); |
585 | | bool GetShadowTransformSetByAnimation() { return mShadowTransformSetByAnimation; } |
586 | | bool GetShadowOpacitySetByAnimation() { return mShadowOpacitySetByAnimation; } |
587 | | |
588 | | void RecomputeShadowVisibleRegionFromChildren(); |
589 | | |
590 | | protected: |
591 | | HostLayerManager* mCompositorManager; |
592 | | |
593 | | gfx::Matrix4x4 mShadowTransform; |
594 | | LayerIntRegion mShadowVisibleRegion; |
595 | | Maybe<ParentLayerIntRect> mShadowClipRect; |
596 | | float mShadowOpacity; |
597 | | bool mShadowTransformSetByAnimation; |
598 | | bool mShadowOpacitySetByAnimation; |
599 | | }; |
600 | | |
601 | | /** |
602 | | * Composite layers are for use with OMTC on the compositor thread only. There |
603 | | * must be corresponding Client layers on the content thread. For composite |
604 | | * layers, the layer manager only maintains the layer tree, all rendering is |
605 | | * done by a Compositor (see Compositor.h). As such, composite layers are |
606 | | * platform-independent and can be used on any platform for which there is a |
607 | | * Compositor implementation. |
608 | | * |
609 | | * The composite layer tree reflects exactly the basic layer tree. To |
610 | | * composite to screen, the layer manager walks the layer tree calling render |
611 | | * methods which in turn call into their CompositableHosts' Composite methods. |
612 | | * These call Compositor::DrawQuad to do the rendering. |
613 | | * |
614 | | * Mostly, layers are updated during the layers transaction. This is done from |
615 | | * CompositableClient to CompositableHost without interacting with the layer. |
616 | | * |
617 | | * A reference to the Compositor is stored in LayerManagerComposite. |
618 | | */ |
619 | | class LayerComposite : public HostLayer |
620 | | { |
621 | | public: |
622 | | explicit LayerComposite(LayerManagerComposite* aManager); |
623 | | |
624 | | virtual ~LayerComposite(); |
625 | | |
626 | | virtual void SetLayerManager(HostLayerManager* aManager) override; |
627 | | |
628 | | virtual LayerComposite* GetFirstChildComposite() override |
629 | 0 | { |
630 | 0 | return nullptr; |
631 | 0 | } |
632 | | |
633 | | /* Do NOT call this from the generic LayerComposite destructor. Only from the |
634 | | * concrete class destructor |
635 | | */ |
636 | | virtual void Destroy(); |
637 | 0 | virtual void Cleanup() {} |
638 | | |
639 | | /** |
640 | | * Perform a first pass over the layer tree to render all of the intermediate |
641 | | * surfaces that we can. This allows us to avoid framebuffer switches in the |
642 | | * middle of our render which is inefficient especially on mobile GPUs. This |
643 | | * must be called before RenderLayer. |
644 | | */ |
645 | 0 | virtual void Prepare(const RenderTargetIntRect& aClipRect) {} |
646 | | |
647 | | // TODO: This should also take RenderTargetIntRect like Prepare. |
648 | | virtual void RenderLayer(const gfx::IntRect& aClipRect, |
649 | | const Maybe<gfx::Polygon>& aGeometry) = 0; |
650 | | |
651 | | virtual bool SetCompositableHost(CompositableHost*) override |
652 | 0 | { |
653 | 0 | // We must handle this gracefully, see bug 967824 |
654 | 0 | NS_WARNING("called SetCompositableHost for a layer type not accepting a compositable"); |
655 | 0 | return false; |
656 | 0 | } |
657 | | |
658 | | virtual void CleanupResources() = 0; |
659 | | |
660 | 0 | virtual void DestroyFrontBuffer() { } |
661 | | |
662 | | void AddBlendModeEffect(EffectChain& aEffectChain); |
663 | | |
664 | 0 | virtual void GenEffectChain(EffectChain& aEffect) { } |
665 | | |
666 | | void SetLayerComposited(bool value) |
667 | 0 | { |
668 | 0 | mLayerComposited = value; |
669 | 0 | } |
670 | | |
671 | | void SetClearRect(const gfx::IntRect& aRect) |
672 | 0 | { |
673 | 0 | mClearRect = aRect; |
674 | 0 | } |
675 | | |
676 | 0 | bool HasLayerBeenComposited() { return mLayerComposited; } |
677 | 0 | gfx::IntRect GetClearRect() { return mClearRect; } |
678 | | |
679 | | // Returns false if the layer is attached to an older compositor. |
680 | | bool HasStaleCompositor() const; |
681 | | |
682 | | /** |
683 | | * Return the part of the visible region that has been fully rendered. |
684 | | * While progressive drawing is in progress this region will be |
685 | | * a subset of the shadow visible region. |
686 | | */ |
687 | | virtual nsIntRegion GetFullyRenderedRegion(); |
688 | | |
689 | | protected: |
690 | | LayerManagerComposite* mCompositeManager; |
691 | | |
692 | | RefPtr<Compositor> mCompositor; |
693 | | bool mDestroyed; |
694 | | bool mLayerComposited; |
695 | | gfx::IntRect mClearRect; |
696 | | }; |
697 | | |
698 | | // Render aLayer using aCompositor and apply all mask layers of aLayer: The |
699 | | // layer's own mask layer (aLayer->GetMaskLayer()), and any ancestor mask |
700 | | // layers. |
701 | | // If more than one mask layer needs to be applied, we use intermediate surfaces |
702 | | // (CompositingRenderTargets) for rendering, applying one mask layer at a time. |
703 | | // Callers need to provide a callback function aRenderCallback that does the |
704 | | // actual rendering of the source. It needs to have the following form: |
705 | | // void (EffectChain& effectChain, const Rect& clipRect) |
706 | | // aRenderCallback is called exactly once, inside this function, unless aLayer's |
707 | | // visible region is completely clipped out (in that case, aRenderCallback won't |
708 | | // be called at all). |
709 | | // This function calls aLayer->AsHostLayer()->AddBlendModeEffect for the |
710 | | // final rendering pass. |
711 | | // |
712 | | // (This function should really live in LayerManagerComposite.cpp, but we |
713 | | // need to use templates for passing lambdas until bug 1164522 is resolved.) |
714 | | template<typename RenderCallbackType> |
715 | | void |
716 | | RenderWithAllMasks(Layer* aLayer, Compositor* aCompositor, |
717 | | const gfx::IntRect& aClipRect, |
718 | | RenderCallbackType aRenderCallback) |
719 | 0 | { |
720 | 0 | Layer* firstMask = nullptr; |
721 | 0 | size_t maskLayerCount = 0; |
722 | 0 | size_t nextAncestorMaskLayer = 0; |
723 | 0 |
|
724 | 0 | size_t ancestorMaskLayerCount = aLayer->GetAncestorMaskLayerCount(); |
725 | 0 | if (Layer* ownMask = aLayer->GetMaskLayer()) { |
726 | 0 | firstMask = ownMask; |
727 | 0 | maskLayerCount = ancestorMaskLayerCount + 1; |
728 | 0 | nextAncestorMaskLayer = 0; |
729 | 0 | } else if (ancestorMaskLayerCount > 0) { |
730 | 0 | firstMask = aLayer->GetAncestorMaskLayerAt(0); |
731 | 0 | maskLayerCount = ancestorMaskLayerCount; |
732 | 0 | nextAncestorMaskLayer = 1; |
733 | 0 | } else { |
734 | 0 | // no mask layers at all |
735 | 0 | } |
736 | 0 |
|
737 | 0 | if (maskLayerCount <= 1) { |
738 | 0 | // This is the common case. Render in one pass and return. |
739 | 0 | EffectChain effectChain(aLayer); |
740 | 0 | LayerManagerComposite::AutoAddMaskEffect |
741 | 0 | autoMaskEffect(firstMask, effectChain); |
742 | 0 | static_cast<LayerComposite*>(aLayer->AsHostLayer())->AddBlendModeEffect(effectChain); |
743 | 0 | aRenderCallback(effectChain, aClipRect); |
744 | 0 | return; |
745 | 0 | } |
746 | 0 | |
747 | 0 | // We have multiple mask layers. |
748 | 0 | // We split our list of mask layers into three parts: |
749 | 0 | // (1) The first mask |
750 | 0 | // (2) The list of intermediate masks (every mask except first and last) |
751 | 0 | // (3) The final mask. |
752 | 0 | // Part (2) can be empty. |
753 | 0 | // For parts (1) and (2) we need to allocate intermediate surfaces to render |
754 | 0 | // into. The final mask gets rendered into the original render target. |
755 | 0 | |
756 | 0 | // Calculate the size of the intermediate surfaces. |
757 | 0 | gfx::Rect visibleRect(aLayer->GetLocalVisibleRegion().GetBounds().ToUnknownRect()); |
758 | 0 | gfx::Matrix4x4 transform = aLayer->GetEffectiveTransform(); |
759 | 0 | // TODO: Use RenderTargetIntRect and TransformBy here |
760 | 0 | gfx::IntRect surfaceRect = |
761 | 0 | RoundedOut(transform.TransformAndClipBounds(visibleRect, gfx::Rect(aClipRect))); |
762 | 0 | if (surfaceRect.IsEmpty()) { |
763 | 0 | return; |
764 | 0 | } |
765 | 0 | |
766 | 0 | RefPtr<CompositingRenderTarget> originalTarget = |
767 | 0 | aCompositor->GetCurrentRenderTarget(); |
768 | 0 |
|
769 | 0 | RefPtr<CompositingRenderTarget> firstTarget = |
770 | 0 | aCompositor->CreateRenderTarget(surfaceRect, INIT_MODE_CLEAR); |
771 | 0 | if (!firstTarget) { |
772 | 0 | return; |
773 | 0 | } |
774 | 0 | |
775 | 0 | // Render the source while applying the first mask. |
776 | 0 | aCompositor->SetRenderTarget(firstTarget); |
777 | 0 | { |
778 | 0 | EffectChain firstEffectChain(aLayer); |
779 | 0 | LayerManagerComposite::AutoAddMaskEffect |
780 | 0 | firstMaskEffect(firstMask, firstEffectChain); |
781 | 0 | aRenderCallback(firstEffectChain, aClipRect - surfaceRect.TopLeft()); |
782 | 0 | // firstTarget now contains the transformed source with the first mask and |
783 | 0 | // opacity already applied. |
784 | 0 | } |
785 | 0 |
|
786 | 0 | // Apply the intermediate masks. |
787 | 0 | gfx::IntRect intermediateClip(surfaceRect - surfaceRect.TopLeft()); |
788 | 0 | RefPtr<CompositingRenderTarget> previousTarget = firstTarget; |
789 | 0 | for (size_t i = nextAncestorMaskLayer; i < ancestorMaskLayerCount - 1; i++) { |
790 | 0 | Layer* intermediateMask = aLayer->GetAncestorMaskLayerAt(i); |
791 | 0 | RefPtr<CompositingRenderTarget> intermediateTarget = |
792 | 0 | aCompositor->CreateRenderTarget(surfaceRect, INIT_MODE_CLEAR); |
793 | 0 | if (!intermediateTarget) { |
794 | 0 | break; |
795 | 0 | } |
796 | 0 | aCompositor->SetRenderTarget(intermediateTarget); |
797 | 0 | EffectChain intermediateEffectChain(aLayer); |
798 | 0 | LayerManagerComposite::AutoAddMaskEffect |
799 | 0 | intermediateMaskEffect(intermediateMask, intermediateEffectChain); |
800 | 0 | if (intermediateMaskEffect.Failed()) { |
801 | 0 | continue; |
802 | 0 | } |
803 | 0 | intermediateEffectChain.mPrimaryEffect = new EffectRenderTarget(previousTarget); |
804 | 0 | aCompositor->DrawQuad(gfx::Rect(surfaceRect), intermediateClip, |
805 | 0 | intermediateEffectChain, 1.0, gfx::Matrix4x4()); |
806 | 0 | previousTarget = intermediateTarget; |
807 | 0 | } |
808 | 0 |
|
809 | 0 | aCompositor->SetRenderTarget(originalTarget); |
810 | 0 |
|
811 | 0 | // Apply the final mask, rendering into originalTarget. |
812 | 0 | EffectChain finalEffectChain(aLayer); |
813 | 0 | finalEffectChain.mPrimaryEffect = new EffectRenderTarget(previousTarget); |
814 | 0 | Layer* finalMask = aLayer->GetAncestorMaskLayerAt(ancestorMaskLayerCount - 1); |
815 | 0 |
|
816 | 0 | // The blend mode needs to be applied in this final step, because this is |
817 | 0 | // where we're blending with the actual background (which is in originalTarget). |
818 | 0 | static_cast<LayerComposite*>(aLayer->AsHostLayer())->AddBlendModeEffect(finalEffectChain); |
819 | 0 | LayerManagerComposite::AutoAddMaskEffect autoMaskEffect(finalMask, finalEffectChain); |
820 | 0 | if (!autoMaskEffect.Failed()) { |
821 | 0 | aCompositor->DrawQuad(gfx::Rect(surfaceRect), aClipRect, |
822 | 0 | finalEffectChain, 1.0, gfx::Matrix4x4()); |
823 | 0 | } |
824 | 0 | } Unexecuted instantiation: Unified_cpp_gfx_layers6.cpp:void mozilla::layers::RenderWithAllMasks<mozilla::layers::CanvasLayerComposite::RenderLayer(mozilla::gfx::IntRectTyped<mozilla::gfx::UnknownUnits> const&, mozilla::Maybe<mozilla::gfx::PolygonTyped<mozilla::gfx::UnknownUnits> > const&)::$_5>(mozilla::layers::Layer*, mozilla::layers::Compositor*, mozilla::gfx::IntRectTyped<mozilla::gfx::UnknownUnits> const&, mozilla::layers::CanvasLayerComposite::RenderLayer(mozilla::gfx::IntRectTyped<mozilla::gfx::UnknownUnits> const&, mozilla::Maybe<mozilla::gfx::PolygonTyped<mozilla::gfx::UnknownUnits> > const&)::$_5) Unexecuted instantiation: Unified_cpp_gfx_layers6.cpp:void mozilla::layers::RenderWithAllMasks<mozilla::layers::ColorLayerComposite::RenderLayer(mozilla::gfx::IntRectTyped<mozilla::gfx::UnknownUnits> const&, mozilla::Maybe<mozilla::gfx::PolygonTyped<mozilla::gfx::UnknownUnits> > const&)::$_6>(mozilla::layers::Layer*, mozilla::layers::Compositor*, mozilla::gfx::IntRectTyped<mozilla::gfx::UnknownUnits> const&, mozilla::layers::ColorLayerComposite::RenderLayer(mozilla::gfx::IntRectTyped<mozilla::gfx::UnknownUnits> const&, mozilla::Maybe<mozilla::gfx::PolygonTyped<mozilla::gfx::UnknownUnits> > const&)::$_6) Unexecuted instantiation: void mozilla::layers::RenderWithAllMasks<void mozilla::layers::ContainerRender<mozilla::layers::ContainerLayerComposite>(mozilla::layers::ContainerLayerComposite*, mozilla::layers::LayerManagerComposite*, mozilla::gfx::IntRectTyped<mozilla::gfx::UnknownUnits> const&, mozilla::Maybe<mozilla::gfx::PolygonTyped<mozilla::gfx::UnknownUnits> > const&)::{lambda(mozilla::layers::EffectChain&, mozilla::gfx::IntRectTyped<mozilla::gfx::UnknownUnits> const&)#1}>(mozilla::layers::Layer*, mozilla::layers::Compositor*, mozilla::gfx::IntRectTyped<mozilla::gfx::UnknownUnits> const&, void mozilla::layers::ContainerRender<mozilla::layers::ContainerLayerComposite>(mozilla::layers::ContainerLayerComposite*, mozilla::layers::LayerManagerComposite*, mozilla::gfx::IntRectTyped<mozilla::gfx::UnknownUnits> const&, mozilla::Maybe<mozilla::gfx::PolygonTyped<mozilla::gfx::UnknownUnits> > const&)::{lambda(mozilla::layers::EffectChain&, mozilla::gfx::IntRectTyped<mozilla::gfx::UnknownUnits> const&)#1}) Unexecuted instantiation: void mozilla::layers::RenderWithAllMasks<void mozilla::layers::ContainerRender<mozilla::layers::RefLayerComposite>(mozilla::layers::RefLayerComposite*, mozilla::layers::LayerManagerComposite*, mozilla::gfx::IntRectTyped<mozilla::gfx::UnknownUnits> const&, mozilla::Maybe<mozilla::gfx::PolygonTyped<mozilla::gfx::UnknownUnits> > const&)::{lambda(mozilla::layers::EffectChain&, mozilla::gfx::IntRectTyped<mozilla::gfx::UnknownUnits> const&)#1}>(mozilla::layers::Layer*, mozilla::layers::Compositor*, mozilla::gfx::IntRectTyped<mozilla::gfx::UnknownUnits> const&, void mozilla::layers::ContainerRender<mozilla::layers::RefLayerComposite>(mozilla::layers::RefLayerComposite*, mozilla::layers::LayerManagerComposite*, mozilla::gfx::IntRectTyped<mozilla::gfx::UnknownUnits> const&, mozilla::Maybe<mozilla::gfx::PolygonTyped<mozilla::gfx::UnknownUnits> > const&)::{lambda(mozilla::layers::EffectChain&, mozilla::gfx::IntRectTyped<mozilla::gfx::UnknownUnits> const&)#1}) Unexecuted instantiation: Unified_cpp_gfx_layers7.cpp:void mozilla::layers::RenderWithAllMasks<mozilla::layers::ImageLayerComposite::RenderLayer(mozilla::gfx::IntRectTyped<mozilla::gfx::UnknownUnits> const&, mozilla::Maybe<mozilla::gfx::PolygonTyped<mozilla::gfx::UnknownUnits> > const&)::$_0>(mozilla::layers::Layer*, mozilla::layers::Compositor*, mozilla::gfx::IntRectTyped<mozilla::gfx::UnknownUnits> const&, mozilla::layers::ImageLayerComposite::RenderLayer(mozilla::gfx::IntRectTyped<mozilla::gfx::UnknownUnits> const&, mozilla::Maybe<mozilla::gfx::PolygonTyped<mozilla::gfx::UnknownUnits> > const&)::$_0) Unexecuted instantiation: Unified_cpp_gfx_layers7.cpp:void mozilla::layers::RenderWithAllMasks<mozilla::layers::PaintedLayerComposite::RenderLayer(mozilla::gfx::IntRectTyped<mozilla::gfx::UnknownUnits> const&, mozilla::Maybe<mozilla::gfx::PolygonTyped<mozilla::gfx::UnknownUnits> > const&)::$_1>(mozilla::layers::Layer*, mozilla::layers::Compositor*, mozilla::gfx::IntRectTyped<mozilla::gfx::UnknownUnits> const&, mozilla::layers::PaintedLayerComposite::RenderLayer(mozilla::gfx::IntRectTyped<mozilla::gfx::UnknownUnits> const&, mozilla::Maybe<mozilla::gfx::PolygonTyped<mozilla::gfx::UnknownUnits> > const&)::$_1) |
825 | | |
826 | | } // namespace layers |
827 | | } // namespace mozilla |
828 | | |
829 | | #endif /* GFX_LayerManagerComposite_H */ |