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.
michael@0 | 1 | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- |
michael@0 | 2 | * vim: sw=2 ts=8 et : |
michael@0 | 3 | */ |
michael@0 | 4 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 7 | |
michael@0 | 8 | #include "CompositableTransactionParent.h" |
michael@0 | 9 | #include "CompositableHost.h" // for CompositableParent, etc |
michael@0 | 10 | #include "CompositorParent.h" // for CompositorParent |
michael@0 | 11 | #include "GLContext.h" // for GLContext |
michael@0 | 12 | #include "Layers.h" // for Layer |
michael@0 | 13 | #include "RenderTrace.h" // for RenderTraceInvalidateEnd, etc |
michael@0 | 14 | #include "TiledLayerBuffer.h" // for TiledLayerComposer |
michael@0 | 15 | #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc |
michael@0 | 16 | #include "mozilla/RefPtr.h" // for RefPtr |
michael@0 | 17 | #include "mozilla/layers/CompositorTypes.h" |
michael@0 | 18 | #include "mozilla/layers/ContentHost.h" // for ContentHostBase |
michael@0 | 19 | #include "mozilla/layers/LayerManagerComposite.h" |
michael@0 | 20 | #include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor |
michael@0 | 21 | #include "mozilla/layers/LayersTypes.h" // for MOZ_LAYERS_LOG |
michael@0 | 22 | #include "mozilla/layers/TextureHost.h" // for TextureHost |
michael@0 | 23 | #include "mozilla/layers/TextureHostOGL.h" // for TextureHostOGL |
michael@0 | 24 | #include "mozilla/layers/ThebesLayerComposite.h" |
michael@0 | 25 | #include "mozilla/mozalloc.h" // for operator delete |
michael@0 | 26 | #include "nsDebug.h" // for NS_WARNING, NS_ASSERTION |
michael@0 | 27 | #include "nsRegion.h" // for nsIntRegion |
michael@0 | 28 | |
michael@0 | 29 | namespace mozilla { |
michael@0 | 30 | namespace layers { |
michael@0 | 31 | |
michael@0 | 32 | class ClientTiledLayerBuffer; |
michael@0 | 33 | class Compositor; |
michael@0 | 34 | |
michael@0 | 35 | template<typename Op> |
michael@0 | 36 | CompositableHost* AsCompositable(const Op& op) |
michael@0 | 37 | { |
michael@0 | 38 | return CompositableHost::FromIPDLActor(op.compositableParent()); |
michael@0 | 39 | } |
michael@0 | 40 | |
michael@0 | 41 | // This function can in some cases fail and return false without it being a bug. |
michael@0 | 42 | // This can theoretically happen if the ImageBridge sends frames before |
michael@0 | 43 | // we created the layer tree. Since we can't enforce that the layer |
michael@0 | 44 | // tree is already created before ImageBridge operates, there isn't much |
michael@0 | 45 | // we can do about it, but in practice it is very rare. |
michael@0 | 46 | // Typically when a tab with a video is dragged from a window to another, |
michael@0 | 47 | // there can be a short time when the video is still sending frames |
michael@0 | 48 | // asynchonously while the layer tree is not reconstructed. It's not a |
michael@0 | 49 | // big deal. |
michael@0 | 50 | // Note that Layers transactions do not need to call this because they always |
michael@0 | 51 | // schedule the composition, in LayerManagerComposite::EndTransaction. |
michael@0 | 52 | template<typename T> |
michael@0 | 53 | bool ScheduleComposition(const T& op) |
michael@0 | 54 | { |
michael@0 | 55 | CompositableHost* comp = AsCompositable(op); |
michael@0 | 56 | uint64_t id = comp->GetCompositorID(); |
michael@0 | 57 | if (!comp || !id) { |
michael@0 | 58 | return false; |
michael@0 | 59 | } |
michael@0 | 60 | CompositorParent* cp = CompositorParent::GetCompositor(id); |
michael@0 | 61 | if (!cp) { |
michael@0 | 62 | return false; |
michael@0 | 63 | } |
michael@0 | 64 | cp->ScheduleComposition(); |
michael@0 | 65 | return true; |
michael@0 | 66 | } |
michael@0 | 67 | |
michael@0 | 68 | bool |
michael@0 | 69 | CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation& aEdit, |
michael@0 | 70 | EditReplyVector& replyv) |
michael@0 | 71 | { |
michael@0 | 72 | switch (aEdit.type()) { |
michael@0 | 73 | case CompositableOperation::TOpCreatedIncrementalTexture: { |
michael@0 | 74 | MOZ_LAYERS_LOG(("[ParentSide] Created texture")); |
michael@0 | 75 | const OpCreatedIncrementalTexture& op = aEdit.get_OpCreatedIncrementalTexture(); |
michael@0 | 76 | CompositableHost* compositable = AsCompositable(op); |
michael@0 | 77 | |
michael@0 | 78 | bool success = |
michael@0 | 79 | compositable->CreatedIncrementalTexture(this, |
michael@0 | 80 | op.textureInfo(), |
michael@0 | 81 | op.bufferRect()); |
michael@0 | 82 | if (!success) { |
michael@0 | 83 | return false; |
michael@0 | 84 | } |
michael@0 | 85 | break; |
michael@0 | 86 | } |
michael@0 | 87 | case CompositableOperation::TOpPaintTextureRegion: { |
michael@0 | 88 | MOZ_LAYERS_LOG(("[ParentSide] Paint ThebesLayer")); |
michael@0 | 89 | |
michael@0 | 90 | const OpPaintTextureRegion& op = aEdit.get_OpPaintTextureRegion(); |
michael@0 | 91 | CompositableHost* compositable = AsCompositable(op); |
michael@0 | 92 | Layer* layer = compositable->GetLayer(); |
michael@0 | 93 | if (!layer || layer->GetType() != Layer::TYPE_THEBES) { |
michael@0 | 94 | return false; |
michael@0 | 95 | } |
michael@0 | 96 | ThebesLayerComposite* thebes = static_cast<ThebesLayerComposite*>(layer); |
michael@0 | 97 | |
michael@0 | 98 | const ThebesBufferData& bufferData = op.bufferData(); |
michael@0 | 99 | |
michael@0 | 100 | RenderTraceInvalidateStart(thebes, "FF00FF", op.updatedRegion().GetBounds()); |
michael@0 | 101 | |
michael@0 | 102 | nsIntRegion frontUpdatedRegion; |
michael@0 | 103 | if (!compositable->UpdateThebes(bufferData, |
michael@0 | 104 | op.updatedRegion(), |
michael@0 | 105 | thebes->GetValidRegion(), |
michael@0 | 106 | &frontUpdatedRegion)) |
michael@0 | 107 | { |
michael@0 | 108 | return false; |
michael@0 | 109 | } |
michael@0 | 110 | replyv.push_back( |
michael@0 | 111 | OpContentBufferSwap(op.compositableParent(), nullptr, frontUpdatedRegion)); |
michael@0 | 112 | |
michael@0 | 113 | RenderTraceInvalidateEnd(thebes, "FF00FF"); |
michael@0 | 114 | // return texure data to client if necessary |
michael@0 | 115 | ReturnTextureDataIfNecessary(compositable, replyv, op.compositableParent()); |
michael@0 | 116 | break; |
michael@0 | 117 | } |
michael@0 | 118 | case CompositableOperation::TOpPaintTextureIncremental: { |
michael@0 | 119 | MOZ_LAYERS_LOG(("[ParentSide] Paint ThebesLayer")); |
michael@0 | 120 | |
michael@0 | 121 | const OpPaintTextureIncremental& op = aEdit.get_OpPaintTextureIncremental(); |
michael@0 | 122 | |
michael@0 | 123 | CompositableHost* compositable = AsCompositable(op); |
michael@0 | 124 | |
michael@0 | 125 | SurfaceDescriptor desc = op.image(); |
michael@0 | 126 | |
michael@0 | 127 | compositable->UpdateIncremental(op.textureId(), |
michael@0 | 128 | desc, |
michael@0 | 129 | op.updatedRegion(), |
michael@0 | 130 | op.bufferRect(), |
michael@0 | 131 | op.bufferRotation()); |
michael@0 | 132 | break; |
michael@0 | 133 | } |
michael@0 | 134 | case CompositableOperation::TOpUpdatePictureRect: { |
michael@0 | 135 | const OpUpdatePictureRect& op = aEdit.get_OpUpdatePictureRect(); |
michael@0 | 136 | CompositableHost* compositable = AsCompositable(op); |
michael@0 | 137 | MOZ_ASSERT(compositable); |
michael@0 | 138 | compositable->SetPictureRect(op.picture()); |
michael@0 | 139 | break; |
michael@0 | 140 | } |
michael@0 | 141 | case CompositableOperation::TOpUseTiledLayerBuffer: { |
michael@0 | 142 | MOZ_LAYERS_LOG(("[ParentSide] Paint TiledLayerBuffer")); |
michael@0 | 143 | const OpUseTiledLayerBuffer& op = aEdit.get_OpUseTiledLayerBuffer(); |
michael@0 | 144 | CompositableHost* compositable = AsCompositable(op); |
michael@0 | 145 | |
michael@0 | 146 | TiledLayerComposer* tileComposer = compositable->AsTiledLayerComposer(); |
michael@0 | 147 | NS_ASSERTION(tileComposer, "compositable is not a tile composer"); |
michael@0 | 148 | |
michael@0 | 149 | const SurfaceDescriptorTiles& tileDesc = op.tileLayerDescriptor(); |
michael@0 | 150 | tileComposer->UseTiledLayerBuffer(this, tileDesc); |
michael@0 | 151 | break; |
michael@0 | 152 | } |
michael@0 | 153 | case CompositableOperation::TOpRemoveTexture: { |
michael@0 | 154 | const OpRemoveTexture& op = aEdit.get_OpRemoveTexture(); |
michael@0 | 155 | CompositableHost* compositable = AsCompositable(op); |
michael@0 | 156 | RefPtr<TextureHost> tex = TextureHost::AsTextureHost(op.textureParent()); |
michael@0 | 157 | |
michael@0 | 158 | MOZ_ASSERT(tex.get()); |
michael@0 | 159 | compositable->RemoveTextureHost(tex); |
michael@0 | 160 | // return texure data to client if necessary |
michael@0 | 161 | ReturnTextureDataIfNecessary(compositable, replyv, op.compositableParent()); |
michael@0 | 162 | break; |
michael@0 | 163 | } |
michael@0 | 164 | case CompositableOperation::TOpUseTexture: { |
michael@0 | 165 | const OpUseTexture& op = aEdit.get_OpUseTexture(); |
michael@0 | 166 | CompositableHost* compositable = AsCompositable(op); |
michael@0 | 167 | RefPtr<TextureHost> tex = TextureHost::AsTextureHost(op.textureParent()); |
michael@0 | 168 | |
michael@0 | 169 | MOZ_ASSERT(tex.get()); |
michael@0 | 170 | compositable->UseTextureHost(tex); |
michael@0 | 171 | |
michael@0 | 172 | if (IsAsync()) { |
michael@0 | 173 | ScheduleComposition(op); |
michael@0 | 174 | // Async layer updates don't trigger invalidation, manually tell the layer |
michael@0 | 175 | // that its content have changed. |
michael@0 | 176 | if (compositable->GetLayer()) { |
michael@0 | 177 | compositable->GetLayer()->SetInvalidRectToVisibleRegion(); |
michael@0 | 178 | } |
michael@0 | 179 | } |
michael@0 | 180 | // return texure data to client if necessary |
michael@0 | 181 | ReturnTextureDataIfNecessary(compositable, replyv, op.compositableParent()); |
michael@0 | 182 | break; |
michael@0 | 183 | } |
michael@0 | 184 | case CompositableOperation::TOpUseComponentAlphaTextures: { |
michael@0 | 185 | const OpUseComponentAlphaTextures& op = aEdit.get_OpUseComponentAlphaTextures(); |
michael@0 | 186 | CompositableHost* compositable = AsCompositable(op); |
michael@0 | 187 | RefPtr<TextureHost> texOnBlack = TextureHost::AsTextureHost(op.textureOnBlackParent()); |
michael@0 | 188 | RefPtr<TextureHost> texOnWhite = TextureHost::AsTextureHost(op.textureOnWhiteParent()); |
michael@0 | 189 | |
michael@0 | 190 | MOZ_ASSERT(texOnBlack && texOnWhite); |
michael@0 | 191 | compositable->UseComponentAlphaTextures(texOnBlack, texOnWhite); |
michael@0 | 192 | |
michael@0 | 193 | if (IsAsync()) { |
michael@0 | 194 | ScheduleComposition(op); |
michael@0 | 195 | } |
michael@0 | 196 | // return texure data to client if necessary |
michael@0 | 197 | ReturnTextureDataIfNecessary(compositable, replyv, op.compositableParent()); |
michael@0 | 198 | break; |
michael@0 | 199 | } |
michael@0 | 200 | case CompositableOperation::TOpUpdateTexture: { |
michael@0 | 201 | const OpUpdateTexture& op = aEdit.get_OpUpdateTexture(); |
michael@0 | 202 | RefPtr<TextureHost> texture = TextureHost::AsTextureHost(op.textureParent()); |
michael@0 | 203 | MOZ_ASSERT(texture); |
michael@0 | 204 | |
michael@0 | 205 | texture->Updated(op.region().type() == MaybeRegion::TnsIntRegion |
michael@0 | 206 | ? &op.region().get_nsIntRegion() |
michael@0 | 207 | : nullptr); // no region means invalidate the entire surface |
michael@0 | 208 | break; |
michael@0 | 209 | } |
michael@0 | 210 | |
michael@0 | 211 | default: { |
michael@0 | 212 | MOZ_ASSERT(false, "bad type"); |
michael@0 | 213 | } |
michael@0 | 214 | } |
michael@0 | 215 | |
michael@0 | 216 | return true; |
michael@0 | 217 | } |
michael@0 | 218 | |
michael@0 | 219 | #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17 |
michael@0 | 220 | void |
michael@0 | 221 | CompositableParentManager::ReturnTextureDataIfNecessary(CompositableHost* aCompositable, |
michael@0 | 222 | EditReplyVector& replyv, |
michael@0 | 223 | PCompositableParent* aParent) |
michael@0 | 224 | { |
michael@0 | 225 | if (!aCompositable || !aCompositable->GetCompositableBackendSpecificData()) { |
michael@0 | 226 | return; |
michael@0 | 227 | } |
michael@0 | 228 | |
michael@0 | 229 | const std::vector< RefPtr<TextureHost> > textureList = |
michael@0 | 230 | aCompositable->GetCompositableBackendSpecificData()->GetPendingReleaseFenceTextureList(); |
michael@0 | 231 | // Return pending Texture data |
michael@0 | 232 | for (size_t i = 0; i < textureList.size(); i++) { |
michael@0 | 233 | // File descriptor number is limited to 4 per IPC message. |
michael@0 | 234 | // See Bug 986253 |
michael@0 | 235 | if (mPrevFenceHandles.size() >= 4) { |
michael@0 | 236 | break; |
michael@0 | 237 | } |
michael@0 | 238 | TextureHostOGL* hostOGL = textureList[i]->AsHostOGL(); |
michael@0 | 239 | PTextureParent* actor = textureList[i]->GetIPDLActor(); |
michael@0 | 240 | if (!hostOGL || !actor) { |
michael@0 | 241 | continue; |
michael@0 | 242 | } |
michael@0 | 243 | android::sp<android::Fence> fence = hostOGL->GetAndResetReleaseFence(); |
michael@0 | 244 | if (fence.get() && fence->isValid()) { |
michael@0 | 245 | FenceHandle handle = FenceHandle(fence); |
michael@0 | 246 | replyv.push_back(ReturnReleaseFence(aParent, nullptr, actor, nullptr, handle)); |
michael@0 | 247 | // Hold fence handle to prevent fence's file descriptor is closed before IPC happens. |
michael@0 | 248 | mPrevFenceHandles.push_back(handle); |
michael@0 | 249 | } |
michael@0 | 250 | } |
michael@0 | 251 | aCompositable->GetCompositableBackendSpecificData()->ClearPendingReleaseFenceTextureList(); |
michael@0 | 252 | } |
michael@0 | 253 | #else |
michael@0 | 254 | void |
michael@0 | 255 | CompositableParentManager::ReturnTextureDataIfNecessary(CompositableHost* aCompositable, |
michael@0 | 256 | EditReplyVector& replyv, |
michael@0 | 257 | PCompositableParent* aParent) |
michael@0 | 258 | { |
michael@0 | 259 | if (!aCompositable || !aCompositable->GetCompositableBackendSpecificData()) { |
michael@0 | 260 | return; |
michael@0 | 261 | } |
michael@0 | 262 | aCompositable->GetCompositableBackendSpecificData()->ClearPendingReleaseFenceTextureList(); |
michael@0 | 263 | } |
michael@0 | 264 | #endif |
michael@0 | 265 | |
michael@0 | 266 | void |
michael@0 | 267 | CompositableParentManager::ClearPrevFenceHandles() |
michael@0 | 268 | { |
michael@0 | 269 | mPrevFenceHandles.clear(); |
michael@0 | 270 | } |
michael@0 | 271 | |
michael@0 | 272 | } // namespace |
michael@0 | 273 | } // namespace |
michael@0 | 274 |