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_BUFFERHOST_H
7 #define MOZILLA_GFX_BUFFERHOST_H
9 #include <stdint.h> // for uint64_t
10 #include <stdio.h> // for FILE
11 #include "gfxRect.h" // for gfxRect
12 #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
13 #include "mozilla/Attributes.h" // for MOZ_OVERRIDE
14 #include "mozilla/RefPtr.h" // for RefPtr, RefCounted, etc
15 #include "mozilla/gfx/Point.h" // for Point
16 #include "mozilla/gfx/Rect.h" // for Rect
17 #include "mozilla/gfx/Types.h" // for Filter
18 #include "mozilla/ipc/ProtocolUtils.h"
19 #include "mozilla/layers/CompositorTypes.h" // for TextureInfo, etc
20 #include "mozilla/layers/LayersTypes.h" // for LayerRenderState, etc
21 #include "mozilla/layers/PCompositableParent.h"
22 #include "mozilla/layers/TextureHost.h" // for TextureHost
23 #include "mozilla/mozalloc.h" // for operator delete
24 #include "nsCOMPtr.h" // for already_AddRefed
25 #include "nsRegion.h" // for nsIntRegion
26 #include "nscore.h" // for nsACString
27 #include "Units.h" // for CSSToScreenScale
29 struct nsIntPoint;
30 struct nsIntRect;
32 namespace mozilla {
33 namespace gfx {
34 class Matrix4x4;
35 class DataSourceSurface;
36 }
38 namespace layers {
40 // Some properties of a Layer required for tiling
41 struct TiledLayerProperties
42 {
43 nsIntRegion mVisibleRegion;
44 nsIntRegion mValidRegion;
45 CSSToScreenScale mEffectiveResolution;
46 };
48 class Layer;
49 class SurfaceDescriptor;
50 class Compositor;
51 class ISurfaceAllocator;
52 class ThebesBufferData;
53 class TiledLayerComposer;
54 class CompositableParentManager;
55 struct EffectChain;
57 /**
58 * A base class for doing CompositableHost and platform dependent task on TextureHost.
59 */
60 class CompositableBackendSpecificData
61 {
62 protected:
63 virtual ~CompositableBackendSpecificData() { }
65 public:
66 NS_INLINE_DECL_REFCOUNTING(CompositableBackendSpecificData)
68 CompositableBackendSpecificData()
69 {
70 }
72 virtual void SetCompositor(Compositor* aCompositor) {}
73 virtual void ClearData()
74 {
75 mCurrentReleaseFenceTexture = nullptr;
76 ClearPendingReleaseFenceTextureList();
77 }
79 /**
80 * Store a texture currently used for Composition.
81 * This function is called when the texutre might receive ReleaseFence
82 * as a result of Composition.
83 */
84 void SetCurrentReleaseFenceTexture(TextureHost* aTexture)
85 {
86 if (mCurrentReleaseFenceTexture) {
87 mPendingReleaseFenceTextures.push_back(mCurrentReleaseFenceTexture);
88 }
89 mCurrentReleaseFenceTexture = aTexture;
90 }
92 virtual std::vector< RefPtr<TextureHost> >& GetPendingReleaseFenceTextureList()
93 {
94 return mPendingReleaseFenceTextures;
95 }
97 virtual void ClearPendingReleaseFenceTextureList()
98 {
99 return mPendingReleaseFenceTextures.clear();
100 }
101 protected:
102 /**
103 * Store a TextureHost currently used for Composition
104 * and it might receive ReleaseFence for the texutre.
105 */
106 RefPtr<TextureHost> mCurrentReleaseFenceTexture;
107 /**
108 * Store TextureHosts that might have ReleaseFence to be delivered
109 * to TextureClient by CompositableHost.
110 */
111 std::vector< RefPtr<TextureHost> > mPendingReleaseFenceTextures;
112 };
114 /**
115 * The compositor-side counterpart to CompositableClient. Responsible for
116 * updating textures and data about textures from IPC and how textures are
117 * composited (tiling, double buffering, etc.).
118 *
119 * Update (for images/canvases) and UpdateThebes (for Thebes) are called during
120 * the layers transaction to update the Compositbale's textures from the
121 * content side. The actual update (and any syncronous upload) is done by the
122 * TextureHost, but it is coordinated by the CompositableHost.
123 *
124 * Composite is called by the owning layer when it is composited. CompositableHost
125 * will use its TextureHost(s) and call Compositor::DrawQuad to do the actual
126 * rendering.
127 */
128 class CompositableHost
129 {
130 protected:
131 virtual ~CompositableHost();
133 public:
134 NS_INLINE_DECL_REFCOUNTING(CompositableHost)
135 CompositableHost(const TextureInfo& aTextureInfo);
137 static TemporaryRef<CompositableHost> Create(const TextureInfo& aTextureInfo);
139 virtual CompositableType GetType() = 0;
141 virtual CompositableBackendSpecificData* GetCompositableBackendSpecificData()
142 {
143 return mBackendData;
144 }
146 virtual void SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData)
147 {
148 mBackendData = aBackendData;
149 }
151 // If base class overrides, it should still call the parent implementation
152 virtual void SetCompositor(Compositor* aCompositor);
154 // composite the contents of this buffer host to the compositor's surface
155 virtual void Composite(EffectChain& aEffectChain,
156 float aOpacity,
157 const gfx::Matrix4x4& aTransform,
158 const gfx::Filter& aFilter,
159 const gfx::Rect& aClipRect,
160 const nsIntRegion* aVisibleRegion = nullptr,
161 TiledLayerProperties* aLayerProperties = nullptr) = 0;
163 /**
164 * Update the content host.
165 * aUpdated is the region which should be updated
166 * aUpdatedRegionBack is the region in aNewBackResult which has been updated
167 */
168 virtual bool UpdateThebes(const ThebesBufferData& aData,
169 const nsIntRegion& aUpdated,
170 const nsIntRegion& aOldValidRegionBack,
171 nsIntRegion* aUpdatedRegionBack)
172 {
173 NS_ERROR("should be implemented or not used");
174 return false;
175 }
177 /**
178 * Update the content host using a surface that only contains the updated
179 * region.
180 *
181 * Takes ownership of aSurface, and is responsible for freeing it.
182 *
183 * @param aTextureId Texture to update.
184 * @param aSurface Surface containing the update area. Its contents are relative
185 * to aUpdated.TopLeft()
186 * @param aUpdated Area of the content host to update.
187 * @param aBufferRect New area covered by the content host.
188 * @param aBufferRotation New buffer rotation.
189 */
190 virtual void UpdateIncremental(TextureIdentifier aTextureId,
191 SurfaceDescriptor& aSurface,
192 const nsIntRegion& aUpdated,
193 const nsIntRect& aBufferRect,
194 const nsIntPoint& aBufferRotation)
195 {
196 MOZ_ASSERT(false, "should be implemented or not used");
197 }
199 /**
200 * Ensure that a suitable texture host exists in this compsitable.
201 *
202 * Only used with ContentHostIncremental.
203 *
204 * No SurfaceDescriptor or TextureIdentifier is provider as we
205 * don't have a single surface for the texture contents, and we
206 * need to allocate our own one to be updated later.
207 */
208 virtual bool CreatedIncrementalTexture(ISurfaceAllocator* aAllocator,
209 const TextureInfo& aTextureInfo,
210 const nsIntRect& aBufferRect)
211 {
212 NS_ERROR("should be implemented or not used");
213 return false;
214 }
216 /**
217 * Returns the front buffer.
218 */
219 virtual TextureHost* GetAsTextureHost() { return nullptr; }
221 virtual LayerRenderState GetRenderState() = 0;
223 virtual void SetPictureRect(const nsIntRect& aPictureRect)
224 {
225 MOZ_ASSERT(false, "Should have been overridden");
226 }
228 /**
229 * Adds a mask effect using this texture as the mask, if possible.
230 * @return true if the effect was added, false otherwise.
231 */
232 bool AddMaskEffect(EffectChain& aEffects,
233 const gfx::Matrix4x4& aTransform,
234 bool aIs3D = false);
236 void RemoveMaskEffect();
238 Compositor* GetCompositor() const
239 {
240 return mCompositor;
241 }
243 Layer* GetLayer() const { return mLayer; }
244 void SetLayer(Layer* aLayer) { mLayer = aLayer; }
246 virtual TiledLayerComposer* AsTiledLayerComposer() { return nullptr; }
248 typedef uint32_t AttachFlags;
249 static const AttachFlags NO_FLAGS = 0;
250 static const AttachFlags ALLOW_REATTACH = 1;
251 static const AttachFlags KEEP_ATTACHED = 2;
252 static const AttachFlags FORCE_DETACH = 2;
254 virtual void Attach(Layer* aLayer,
255 Compositor* aCompositor,
256 AttachFlags aFlags = NO_FLAGS)
257 {
258 MOZ_ASSERT(aCompositor, "Compositor is required");
259 NS_ASSERTION(aFlags & ALLOW_REATTACH || !mAttached,
260 "Re-attaching compositables must be explicitly authorised");
261 SetCompositor(aCompositor);
262 SetLayer(aLayer);
263 mAttached = true;
264 mKeepAttached = aFlags & KEEP_ATTACHED;
265 }
266 // Detach this compositable host from its layer.
267 // If we are used for async video, then it is not safe to blindly detach since
268 // we might be re-attached to a different layer. aLayer is the layer which the
269 // caller expects us to be attached to, we will only detach if we are in fact
270 // attached to that layer. If we are part of a normal layer, then we will be
271 // detached in any case. if aLayer is null, then we will only detach if we are
272 // not async.
273 // Only force detach if the IPDL tree is being shutdown.
274 void Detach(Layer* aLayer = nullptr, AttachFlags aFlags = NO_FLAGS)
275 {
276 if (!mKeepAttached ||
277 aLayer == mLayer ||
278 aFlags & FORCE_DETACH) {
279 SetLayer(nullptr);
280 mAttached = false;
281 mKeepAttached = false;
282 if (mBackendData) {
283 mBackendData->ClearData();
284 }
285 }
286 }
287 bool IsAttached() { return mAttached; }
289 #ifdef MOZ_DUMP_PAINTING
290 virtual void Dump(FILE* aFile=nullptr,
291 const char* aPrefix="",
292 bool aDumpHtml=false) { }
293 static void DumpTextureHost(FILE* aFile, TextureHost* aTexture);
295 virtual TemporaryRef<gfx::DataSourceSurface> GetAsSurface() { return nullptr; }
296 #endif
298 virtual void PrintInfo(nsACString& aTo, const char* aPrefix) { }
300 virtual void UseTextureHost(TextureHost* aTexture);
301 virtual void UseComponentAlphaTextures(TextureHost* aTextureOnBlack,
302 TextureHost* aTextureOnWhite);
304 virtual void RemoveTextureHost(TextureHost* aTexture);
306 // Called every time this is composited
307 void BumpFlashCounter() {
308 mFlashCounter = mFlashCounter >= DIAGNOSTIC_FLASH_COUNTER_MAX
309 ? DIAGNOSTIC_FLASH_COUNTER_MAX : mFlashCounter + 1;
310 }
312 static PCompositableParent*
313 CreateIPDLActor(CompositableParentManager* mgr,
314 const TextureInfo& textureInfo,
315 uint64_t asyncID);
317 static bool DestroyIPDLActor(PCompositableParent* actor);
319 static CompositableHost* FromIPDLActor(PCompositableParent* actor);
321 uint64_t GetCompositorID() const { return mCompositorID; }
323 uint64_t GetAsyncID() const { return mAsyncID; }
325 void SetCompositorID(uint64_t aID) { mCompositorID = aID; }
327 void SetAsyncID(uint64_t aID) { mAsyncID = aID; }
329 protected:
330 TextureInfo mTextureInfo;
331 uint64_t mAsyncID;
332 uint64_t mCompositorID;
333 Compositor* mCompositor;
334 Layer* mLayer;
335 RefPtr<CompositableBackendSpecificData> mBackendData;
336 uint32_t mFlashCounter; // used when the pref "layers.flash-borders" is true.
337 bool mAttached;
338 bool mKeepAttached;
339 };
341 /**
342 * Global CompositableMap, to use in the compositor thread only.
343 *
344 * PCompositable and PLayer can, in the case of async textures, be managed by
345 * different top level protocols. In this case they don't share the same
346 * communication channel and we can't send an OpAttachCompositable (PCompositable,
347 * PLayer) message.
348 *
349 * In order to attach a layer and the right compositable if the the compositable
350 * is async, we store references to the async compositables in a CompositableMap
351 * that is accessed only on the compositor thread. During a layer transaction we
352 * send the message OpAttachAsyncCompositable(ID, PLayer), and on the compositor
353 * side we lookup the ID in the map and attach the correspondig compositable to
354 * the layer.
355 *
356 * CompositableMap must be global because the image bridge doesn't have any
357 * reference to whatever we have created with PLayerTransaction. So, the only way to
358 * actually connect these two worlds is to have something global that they can
359 * both query (in the same thread). The map is not allocated the map on the
360 * stack to avoid the badness of static initialization.
361 *
362 * Also, we have a compositor/PLayerTransaction protocol/etc. per layer manager, and the
363 * ImageBridge is used by all the existing compositors that have a video, so
364 * there isn't an instance or "something" that lives outside the boudaries of a
365 * given layer manager on the compositor thread except the image bridge and the
366 * thread itself.
367 */
368 namespace CompositableMap {
369 void Create();
370 void Destroy();
371 PCompositableParent* Get(uint64_t aID);
372 void Set(uint64_t aID, PCompositableParent* aParent);
373 void Erase(uint64_t aID);
374 void Clear();
375 } // CompositableMap
378 } // namespace
379 } // namespace
381 #endif