Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef MOZILLA_GFX_COMPOSITOR_H
7 #define MOZILLA_GFX_COMPOSITOR_H
9 #include "Units.h" // for ScreenPoint
10 #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
11 #include "mozilla/RefPtr.h" // for TemporaryRef, RefCounted
12 #include "mozilla/gfx/Point.h" // for IntSize, Point
13 #include "mozilla/gfx/Rect.h" // for Rect, IntRect
14 #include "mozilla/gfx/Types.h" // for Float
15 #include "mozilla/layers/CompositorTypes.h" // for DiagnosticTypes, etc
16 #include "mozilla/layers/LayersTypes.h" // for LayersBackend
17 #include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc
18 #include "nsRegion.h"
19 #include <vector>
20 #include "mozilla/WidgetUtils.h"
22 /**
23 * Different elements of a web pages are rendered into separate "layers" before
24 * they are flattened into the final image that is brought to the screen.
25 * See Layers.h for more informations about layers and why we use retained
26 * structures.
27 * Most of the documentation for layers is directly in the source code in the
28 * form of doc comments. An overview can also be found in the the wiki:
29 * https://wiki.mozilla.org/Gecko:Overview#Graphics
30 *
31 *
32 * # Main interfaces and abstractions
33 *
34 * - Layer, ShadowableLayer and LayerComposite
35 * (see Layers.h and ipc/ShadowLayers.h)
36 * - CompositableClient and CompositableHost
37 * (client/CompositableClient.h composite/CompositableHost.h)
38 * - TextureClient and TextureHost
39 * (client/TextureClient.h composite/TextureHost.h)
40 * - TextureSource
41 * (composite/TextureHost.h)
42 * - Forwarders
43 * (ipc/CompositableForwarder.h ipc/ShadowLayers.h)
44 * - Compositor
45 * (this file)
46 * - IPDL protocols
47 * (.ipdl files under the gfx/layers/ipc directory)
48 *
49 * The *Client and Shadowable* classes are always used on the content thread.
50 * Forwarders are always used on the content thread.
51 * The *Host and Shadow* classes are always used on the compositor thread.
52 * Compositors, TextureSource, and Effects are always used on the compositor
53 * thread.
54 * Most enums and constants are declared in LayersTypes.h and CompositorTypes.h.
55 *
56 *
57 * # Texture transfer
58 *
59 * Most layer classes own a Compositable plus some extra information like
60 * transforms and clip rects. They are platform independent.
61 * Compositable classes manipulate Texture objects and are reponsible for
62 * things like tiling, buffer rotation or double buffering. Compositables
63 * are also platform-independent. Examples of compositable classes are:
64 * - ImageClient
65 * - CanvasClient
66 * - ContentHost
67 * - etc.
68 * Texture classes (TextureClient and TextureHost) are thin abstractions over
69 * platform-dependent texture memory. They are maniplulated by compositables
70 * and don't know about buffer rotations and such. The purposes of TextureClient
71 * and TextureHost are to synchronize, serialize and deserialize texture data.
72 * TextureHosts provide access to TextureSources that are views on the
73 * Texture data providing the necessary api for Compositor backend to composite
74 * them.
75 *
76 * Compositable and Texture clients and hosts are created using factory methods.
77 * They should only be created by using their constructor in exceptional
78 * circumstances. The factory methods are located:
79 * TextureClient - CompositableClient::CreateTextureClient
80 * TextureHost - TextureHost::CreateTextureHost, which calls a
81 * platform-specific function, e.g., CreateTextureHostOGL
82 * CompositableClient - in the appropriate subclass, e.g.,
83 * CanvasClient::CreateCanvasClient
84 * CompositableHost - CompositableHost::Create
85 *
86 *
87 * # IPDL
88 *
89 * If off-main-thread compositing (OMTC) is enabled, compositing is performed
90 * in a dedicated thread. In some setups compositing happens in a dedicated
91 * process. Documentation may refer to either the compositor thread or the
92 * compositor process.
93 * See explanations in ShadowLayers.h.
94 *
95 *
96 * # Backend implementations
97 *
98 * Compositor backends like OpenGL or flavours of D3D live in their own directory
99 * under gfx/layers/. To add a new backend, implement at least the following
100 * interfaces:
101 * - Compositor (ex. CompositorOGL)
102 * - TextureHost (ex. SharedTextureHostOGL)
103 * Depending on the type of data that needs to be serialized, you may need to
104 * add specific TextureClient implementations.
105 */
107 class nsIWidget;
108 struct nsIntSize;
109 class nsIntRegion;
111 namespace mozilla {
112 namespace gfx {
113 class Matrix;
114 class Matrix4x4;
115 class DrawTarget;
116 }
118 namespace layers {
120 struct Effect;
121 struct EffectChain;
122 class Image;
123 class ISurfaceAllocator;
124 class Layer;
125 class NewTextureSource;
126 class DataTextureSource;
127 class CompositingRenderTarget;
128 class PCompositorParent;
129 class LayerManagerComposite;
131 enum SurfaceInitMode
132 {
133 INIT_MODE_NONE,
134 INIT_MODE_CLEAR
135 };
137 /**
138 * A base class for a platform-dependent helper for use by TextureHost.
139 */
140 class CompositorBackendSpecificData
141 {
142 NS_INLINE_DECL_REFCOUNTING(CompositorBackendSpecificData)
144 protected:
145 virtual ~CompositorBackendSpecificData() {}
146 };
148 /**
149 * Common interface for compositor backends.
150 *
151 * Compositor provides a cross-platform interface to a set of operations for
152 * compositing quads. Compositor knows nothing about the layer tree. It must be
153 * told everything about each composited quad - contents, location, transform,
154 * opacity, etc.
155 *
156 * In theory it should be possible for different widgets to use the same
157 * compositor. In practice, we use one compositor per window.
158 *
159 * # Usage
160 *
161 * For an example of a user of Compositor, see LayerManagerComposite.
162 *
163 * Initialization: create a Compositor object, call Initialize().
164 *
165 * Destruction: destroy any resources associated with the compositor, call
166 * Destroy(), delete the Compositor object.
167 *
168 * Composition:
169 * call BeginFrame,
170 * for each quad to be composited:
171 * call MakeCurrent if necessary (not necessary if no other context has been
172 * made current),
173 * take care of any texture upload required to composite the quad, this step
174 * is backend-dependent,
175 * construct an EffectChain for the quad,
176 * call DrawQuad,
177 * call EndFrame.
178 * If the user has to stop compositing at any point before EndFrame, call
179 * AbortFrame.
180 * If the compositor is usually used for compositing but compositing is
181 * temporarily done without the compositor, call EndFrameForExternalComposition
182 * after compositing each frame so the compositor can remain internally
183 * consistent.
184 *
185 * By default, the compositor will render to the screen, to render to a target,
186 * call SetTargetContext or SetRenderTarget, the latter with a target created
187 * by CreateRenderTarget or CreateRenderTargetFromSource.
188 *
189 * The target and viewport methods can be called before any DrawQuad call and
190 * affect any subsequent DrawQuad calls.
191 */
192 class Compositor
193 {
194 protected:
195 virtual ~Compositor() {}
197 public:
198 NS_INLINE_DECL_REFCOUNTING(Compositor)
200 Compositor(PCompositorParent* aParent = nullptr)
201 : mCompositorID(0)
202 , mDiagnosticTypes(DIAGNOSTIC_NONE)
203 , mParent(aParent)
204 , mScreenRotation(ROTATION_0)
205 {
206 }
208 virtual TemporaryRef<DataTextureSource> CreateDataTextureSource(TextureFlags aFlags = 0) = 0;
209 virtual bool Initialize() = 0;
210 virtual void Destroy() = 0;
212 /**
213 * Return true if the effect type is supported.
214 *
215 * By default Compositor implementations should support all effects but in
216 * some rare cases it is not possible to support an effect efficiently.
217 * This is the case for BasicCompositor with EffectYCbCr.
218 */
219 virtual bool SupportsEffect(EffectTypes aEffect) { return true; }
221 /**
222 * Request a texture host identifier that may be used for creating textures
223 * across process or thread boundaries that are compatible with this
224 * compositor.
225 */
226 virtual TextureFactoryIdentifier GetTextureFactoryIdentifier() = 0;
228 /**
229 * Properties of the compositor.
230 */
231 virtual bool CanUseCanvasLayerForSize(const gfx::IntSize& aSize) = 0;
232 virtual int32_t GetMaxTextureSize() const = 0;
234 /**
235 * Set the target for rendering. Results will have been written to aTarget by
236 * the time that EndFrame returns.
237 *
238 * If this method is not used, or we pass in nullptr, we target the compositor's
239 * usual swap chain and render to the screen.
240 */
241 virtual void SetTargetContext(gfx::DrawTarget* aTarget) = 0;
243 typedef uint32_t MakeCurrentFlags;
244 static const MakeCurrentFlags ForceMakeCurrent = 0x1;
245 /**
246 * Make this compositor's rendering context the current context for the
247 * underlying graphics API. This may be a global operation, depending on the
248 * API. Our context will remain the current one until someone else changes it.
249 *
250 * Clients of the compositor should call this at the start of the compositing
251 * process, it might be required by texture uploads etc.
252 *
253 * If aFlags == ForceMakeCurrent then we will (re-)set our context on the
254 * underlying API even if it is already the current context.
255 */
256 virtual void MakeCurrent(MakeCurrentFlags aFlags = 0) = 0;
258 /**
259 * Creates a Surface that can be used as a rendering target by this
260 * compositor.
261 */
262 virtual TemporaryRef<CompositingRenderTarget>
263 CreateRenderTarget(const gfx::IntRect& aRect, SurfaceInitMode aInit) = 0;
265 /**
266 * Creates a Surface that can be used as a rendering target by this
267 * compositor, and initializes the surface by copying from aSource.
268 * If aSource is null, then the current screen buffer is used as source.
269 *
270 * aSourcePoint specifies the point in aSource to copy data from.
271 */
272 virtual TemporaryRef<CompositingRenderTarget>
273 CreateRenderTargetFromSource(const gfx::IntRect& aRect,
274 const CompositingRenderTarget* aSource,
275 const gfx::IntPoint& aSourcePoint) = 0;
277 /**
278 * Sets the given surface as the target for subsequent calls to DrawQuad.
279 * Passing null as aSurface sets the screen as the target.
280 */
281 virtual void SetRenderTarget(CompositingRenderTarget* aSurface) = 0;
283 /**
284 * Returns the current target for rendering. Will return null if we are
285 * rendering to the screen.
286 */
287 virtual CompositingRenderTarget* GetCurrentRenderTarget() const = 0;
289 /**
290 * Mostly the compositor will pull the size from a widget and this method will
291 * be ignored, but compositor implementations are free to use it if they like.
292 */
293 virtual void SetDestinationSurfaceSize(const gfx::IntSize& aSize) = 0;
295 /**
296 * Declare an offset to use when rendering layers. This will be ignored when
297 * rendering to a target instead of the screen.
298 */
299 virtual void SetScreenRenderOffset(const ScreenPoint& aOffset) = 0;
301 /**
302 * Tell the compositor to draw a quad. What to do draw and how it is
303 * drawn is specified by aEffectChain. aRect is the quad to draw, in user space.
304 * aTransform transforms from user space to screen space. If texture coords are
305 * required, these will be in the primary effect in the effect chain.
306 */
307 virtual void DrawQuad(const gfx::Rect& aRect, const gfx::Rect& aClipRect,
308 const EffectChain& aEffectChain,
309 gfx::Float aOpacity, const gfx::Matrix4x4 &aTransform) = 0;
311 /**
312 * Tell the compositor to draw lines connecting the points. Behaves like
313 * DrawQuad.
314 */
315 virtual void DrawLines(const std::vector<gfx::Point>& aLines, const gfx::Rect& aClipRect,
316 const gfx::Color& aColor,
317 gfx::Float aOpacity, const gfx::Matrix4x4 &aTransform)
318 { /* Should turn into pure virtual once implemented in D3D */ }
320 /*
321 * Clear aRect on current render target.
322 */
323 virtual void ClearRect(const gfx::Rect& aRect) { }
325 /**
326 * Start a new frame.
327 *
328 * aInvalidRect is the invalid region of the screen; it can be ignored for
329 * compositors where the performance for compositing the entire window is
330 * sufficient.
331 *
332 * aClipRectIn is the clip rect for the window in window space (optional).
333 * aTransform is the transform from user space to window space.
334 * aRenderBounds bounding rect for rendering, in user space.
335 *
336 * If aClipRectIn is null, this method sets *aClipRectOut to the clip rect
337 * actually used for rendering (if aClipRectIn is non-null, we will use that
338 * for the clip rect).
339 *
340 * If aRenderBoundsOut is non-null, it will be set to the render bounds
341 * actually used by the compositor in window space. If aRenderBoundsOut
342 * is returned empty, composition should be aborted.
343 */
344 virtual void BeginFrame(const nsIntRegion& aInvalidRegion,
345 const gfx::Rect* aClipRectIn,
346 const gfx::Matrix& aTransform,
347 const gfx::Rect& aRenderBounds,
348 gfx::Rect* aClipRectOut = nullptr,
349 gfx::Rect* aRenderBoundsOut = nullptr) = 0;
351 /**
352 * Flush the current frame to the screen and tidy up.
353 */
354 virtual void EndFrame() = 0;
356 virtual void SetFBAcquireFence(Layer* aLayer) {}
358 /**
359 * Post-rendering stuff if the rendering is done outside of this Compositor
360 * e.g., by Composer2D.
361 * aTransform is the transform from user space to window space.
362 */
363 virtual void EndFrameForExternalComposition(const gfx::Matrix& aTransform) = 0;
365 /**
366 * Tidy up if BeginFrame has been called, but EndFrame won't be.
367 */
368 virtual void AbortFrame() = 0;
370 /**
371 * Setup the viewport and projection matrix for rendering to a target of the
372 * given dimensions. The size and transform here will override those set in
373 * BeginFrame. BeginFrame sets a size and transform for the default render
374 * target, usually the screen. Calling this method prepares the compositor to
375 * render using a different viewport (that is, size and transform), usually
376 * associated with a new render target.
377 * aWorldTransform is the transform from user space to the new viewport's
378 * coordinate space.
379 */
380 virtual void PrepareViewport(const gfx::IntSize& aSize,
381 const gfx::Matrix& aWorldTransform) = 0;
383 /**
384 * Whether textures created by this compositor can receive partial updates.
385 */
386 virtual bool SupportsPartialTextureUpdate() = 0;
388 void SetDiagnosticTypes(DiagnosticTypes aDiagnostics)
389 {
390 mDiagnosticTypes = aDiagnostics;
391 }
393 DiagnosticTypes GetDiagnosticTypes() const
394 {
395 return mDiagnosticTypes;
396 }
398 void DrawDiagnostics(DiagnosticFlags aFlags,
399 const gfx::Rect& visibleRect,
400 const gfx::Rect& aClipRect,
401 const gfx::Matrix4x4& transform,
402 uint32_t aFlashCounter = DIAGNOSTIC_FLASH_COUNTER_MAX);
404 void DrawDiagnostics(DiagnosticFlags aFlags,
405 const nsIntRegion& visibleRegion,
406 const gfx::Rect& aClipRect,
407 const gfx::Matrix4x4& transform,
408 uint32_t aFlashCounter = DIAGNOSTIC_FLASH_COUNTER_MAX);
410 #ifdef MOZ_DUMP_PAINTING
411 virtual const char* Name() const = 0;
412 #endif // MOZ_DUMP_PAINTING
414 virtual LayersBackend GetBackendType() const = 0;
416 /**
417 * Each Compositor has a unique ID.
418 * This ID is used to keep references to each Compositor in a map accessed
419 * from the compositor thread only, so that async compositables can find
420 * the right compositor parent and schedule compositing even if the compositor
421 * changed.
422 */
423 uint32_t GetCompositorID() const
424 {
425 return mCompositorID;
426 }
427 void SetCompositorID(uint32_t aID)
428 {
429 MOZ_ASSERT(mCompositorID == 0, "The compositor ID must be set only once.");
430 mCompositorID = aID;
431 }
433 /**
434 * Notify the compositor that composition is being paused. This allows the
435 * compositor to temporarily release any resources.
436 * Between calling Pause and Resume, compositing may fail.
437 */
438 virtual void Pause() {}
439 /**
440 * Notify the compositor that composition is being resumed. The compositor
441 * regain any resources it requires for compositing.
442 * Returns true if succeeded.
443 */
444 virtual bool Resume() { return true; }
446 /**
447 * Call before rendering begins to ensure the compositor is ready to
448 * composite. Returns false if rendering should be aborted.
449 */
450 virtual bool Ready() { return true; }
452 // XXX I expect we will want to move mWidget into this class and implement
453 // these methods properly.
454 virtual nsIWidget* GetWidget() const { return nullptr; }
456 /**
457 * Debug-build assertion that can be called to ensure code is running on the
458 * compositor thread.
459 */
460 static void AssertOnCompositorThread();
462 /**
463 * We enforce that there can only be one Compositor backend type off the main
464 * thread at the same time. The backend type in use can be checked with this
465 * static method. We need this for creating texture clients/hosts etc. when we
466 * don't have a reference to a Compositor.
467 *
468 * This can only be used from the compositor thread!
469 */
470 static LayersBackend GetBackend();
472 size_t GetFillRatio() {
473 float fillRatio = 0;
474 if (mPixelsFilled > 0 && mPixelsPerFrame > 0) {
475 fillRatio = 100.0f * float(mPixelsFilled) / float(mPixelsPerFrame);
476 if (fillRatio > 999.0f) {
477 fillRatio = 999.0f;
478 }
479 }
480 return fillRatio;
481 }
483 virtual CompositorBackendSpecificData* GetCompositorBackendSpecificData() {
484 return nullptr;
485 }
487 ScreenRotation GetScreenRotation() const {
488 return mScreenRotation;
489 }
491 void SetScreenRotation(ScreenRotation aRotation) {
492 mScreenRotation = aRotation;
493 }
495 // On b2g the clip rect is in the coordinate space of the physical screen
496 // independently of its rotation, while the coordinate space of the layers,
497 // on the other hand, depends on the screen orientation.
498 // This only applies to b2g as with other platforms, orientation is handled
499 // at the OS level rather than in Gecko.
500 // In addition, the clip rect needs to be offset by the rendering origin.
501 // This becomes important if intermediate surfaces are used.
502 gfx::Rect ClipRectInLayersCoordinates(gfx::Rect aClip) const;
504 protected:
505 void DrawDiagnosticsInternal(DiagnosticFlags aFlags,
506 const gfx::Rect& aVisibleRect,
507 const gfx::Rect& aClipRect,
508 const gfx::Matrix4x4& transform,
509 uint32_t aFlashCounter);
511 bool ShouldDrawDiagnostics(DiagnosticFlags);
513 /**
514 * Set the global Compositor backend, checking that one isn't already set.
515 */
516 static void SetBackend(LayersBackend backend);
518 uint32_t mCompositorID;
519 DiagnosticTypes mDiagnosticTypes;
520 PCompositorParent* mParent;
522 /**
523 * We keep track of the total number of pixels filled as we composite the
524 * current frame. This value is an approximation and is not accurate,
525 * especially in the presence of transforms.
526 */
527 size_t mPixelsPerFrame;
528 size_t mPixelsFilled;
530 ScreenRotation mScreenRotation;
532 virtual gfx::IntSize GetWidgetSize() const = 0;
534 private:
535 static LayersBackend sBackend;
537 };
539 } // namespace layers
540 } // namespace mozilla
542 #endif /* MOZILLA_GFX_COMPOSITOR_H */