Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
michael@0 | 1 | /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- |
michael@0 | 2 | * This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 5 | |
michael@0 | 6 | #include "ContainerLayerComposite.h" |
michael@0 | 7 | #include <algorithm> // for min |
michael@0 | 8 | #include "FrameMetrics.h" // for FrameMetrics |
michael@0 | 9 | #include "Units.h" // for LayerRect, LayerPixel, etc |
michael@0 | 10 | #include "gfx2DGlue.h" // for ToMatrix4x4 |
michael@0 | 11 | #include "gfx3DMatrix.h" // for gfx3DMatrix |
michael@0 | 12 | #include "gfxPrefs.h" // for gfxPrefs |
michael@0 | 13 | #include "gfxUtils.h" // for gfxUtils, etc |
michael@0 | 14 | #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc |
michael@0 | 15 | #include "mozilla/RefPtr.h" // for RefPtr |
michael@0 | 16 | #include "mozilla/gfx/BaseRect.h" // for BaseRect |
michael@0 | 17 | #include "mozilla/gfx/Matrix.h" // for Matrix4x4 |
michael@0 | 18 | #include "mozilla/gfx/Point.h" // for Point, IntPoint |
michael@0 | 19 | #include "mozilla/gfx/Rect.h" // for IntRect, Rect |
michael@0 | 20 | #include "mozilla/layers/Compositor.h" // for Compositor, etc |
michael@0 | 21 | #include "mozilla/layers/CompositorTypes.h" // for DIAGNOSTIC_CONTAINER |
michael@0 | 22 | #include "mozilla/layers/Effects.h" // for Effect, EffectChain, etc |
michael@0 | 23 | #include "mozilla/layers/TextureHost.h" // for CompositingRenderTarget |
michael@0 | 24 | #include "mozilla/mozalloc.h" // for operator delete, etc |
michael@0 | 25 | #include "nsAutoPtr.h" // for nsRefPtr |
michael@0 | 26 | #include "nsDebug.h" // for NS_ASSERTION |
michael@0 | 27 | #include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc |
michael@0 | 28 | #include "nsISupportsUtils.h" // for NS_ADDREF, NS_RELEASE |
michael@0 | 29 | #include "nsPoint.h" // for nsIntPoint |
michael@0 | 30 | #include "nsRect.h" // for nsIntRect |
michael@0 | 31 | #include "nsRegion.h" // for nsIntRegion |
michael@0 | 32 | #include "nsTArray.h" // for nsAutoTArray |
michael@0 | 33 | #include "TextRenderer.h" // for TextRenderer |
michael@0 | 34 | #include <vector> |
michael@0 | 35 | |
michael@0 | 36 | namespace mozilla { |
michael@0 | 37 | namespace layers { |
michael@0 | 38 | |
michael@0 | 39 | /** |
michael@0 | 40 | * Returns a rectangle of content painted opaquely by aLayer. Very consertative; |
michael@0 | 41 | * bails by returning an empty rect in any tricky situations. |
michael@0 | 42 | */ |
michael@0 | 43 | static nsIntRect |
michael@0 | 44 | GetOpaqueRect(Layer* aLayer) |
michael@0 | 45 | { |
michael@0 | 46 | nsIntRect result; |
michael@0 | 47 | gfx::Matrix matrix; |
michael@0 | 48 | bool is2D = aLayer->GetBaseTransform().Is2D(&matrix); |
michael@0 | 49 | |
michael@0 | 50 | // Just bail if there's anything difficult to handle. |
michael@0 | 51 | if (!is2D || aLayer->GetMaskLayer() || |
michael@0 | 52 | aLayer->GetEffectiveOpacity() != 1.0f || |
michael@0 | 53 | matrix.HasNonIntegerTranslation()) { |
michael@0 | 54 | return result; |
michael@0 | 55 | } |
michael@0 | 56 | |
michael@0 | 57 | if (aLayer->GetContentFlags() & Layer::CONTENT_OPAQUE) { |
michael@0 | 58 | result = aLayer->GetEffectiveVisibleRegion().GetLargestRectangle(); |
michael@0 | 59 | } else { |
michael@0 | 60 | // Drill down into RefLayers because that's what we particularly care about; |
michael@0 | 61 | // layer construction for aLayer will not have known about the opaqueness |
michael@0 | 62 | // of any RefLayer subtrees. |
michael@0 | 63 | RefLayer* refLayer = aLayer->AsRefLayer(); |
michael@0 | 64 | if (refLayer && refLayer->GetFirstChild()) { |
michael@0 | 65 | result = GetOpaqueRect(refLayer->GetFirstChild()); |
michael@0 | 66 | } |
michael@0 | 67 | } |
michael@0 | 68 | |
michael@0 | 69 | // Translate our opaque region to cover the child |
michael@0 | 70 | gfx::Point point = matrix.GetTranslation(); |
michael@0 | 71 | result.MoveBy(static_cast<int>(point.x), static_cast<int>(point.y)); |
michael@0 | 72 | |
michael@0 | 73 | const nsIntRect* clipRect = aLayer->GetEffectiveClipRect(); |
michael@0 | 74 | if (clipRect) { |
michael@0 | 75 | result.IntersectRect(result, *clipRect); |
michael@0 | 76 | } |
michael@0 | 77 | |
michael@0 | 78 | return result; |
michael@0 | 79 | } |
michael@0 | 80 | |
michael@0 | 81 | struct LayerVelocityUserData : public LayerUserData { |
michael@0 | 82 | public: |
michael@0 | 83 | LayerVelocityUserData() { |
michael@0 | 84 | MOZ_COUNT_CTOR(LayerVelocityUserData); |
michael@0 | 85 | } |
michael@0 | 86 | ~LayerVelocityUserData() { |
michael@0 | 87 | MOZ_COUNT_DTOR(LayerVelocityUserData); |
michael@0 | 88 | } |
michael@0 | 89 | |
michael@0 | 90 | struct VelocityData { |
michael@0 | 91 | VelocityData(TimeStamp frameTime, int scrollX, int scrollY) |
michael@0 | 92 | : mFrameTime(frameTime) |
michael@0 | 93 | , mPoint(scrollX, scrollY) |
michael@0 | 94 | {} |
michael@0 | 95 | |
michael@0 | 96 | TimeStamp mFrameTime; |
michael@0 | 97 | gfx::Point mPoint; |
michael@0 | 98 | }; |
michael@0 | 99 | std::vector<VelocityData> mData; |
michael@0 | 100 | }; |
michael@0 | 101 | |
michael@0 | 102 | static gfx::Point GetScrollData(Layer* aLayer) { |
michael@0 | 103 | gfx::Matrix matrix; |
michael@0 | 104 | if (aLayer->GetLocalTransform().Is2D(&matrix)) { |
michael@0 | 105 | return matrix.GetTranslation(); |
michael@0 | 106 | } |
michael@0 | 107 | |
michael@0 | 108 | gfx::Point origin; |
michael@0 | 109 | return origin; |
michael@0 | 110 | } |
michael@0 | 111 | |
michael@0 | 112 | static void DrawLayerInfo(const nsIntRect& aClipRect, |
michael@0 | 113 | LayerManagerComposite* aManager, |
michael@0 | 114 | Layer* aLayer) |
michael@0 | 115 | { |
michael@0 | 116 | |
michael@0 | 117 | if (aLayer->GetType() == Layer::LayerType::TYPE_CONTAINER) { |
michael@0 | 118 | // XXX - should figure out a way to render this, but for now this |
michael@0 | 119 | // is hard to do, since it will often get superimposed over the first |
michael@0 | 120 | // child of the layer, which is bad. |
michael@0 | 121 | return; |
michael@0 | 122 | } |
michael@0 | 123 | |
michael@0 | 124 | nsAutoCString layerInfo; |
michael@0 | 125 | aLayer->PrintInfo(layerInfo, ""); |
michael@0 | 126 | |
michael@0 | 127 | nsIntRegion visibleRegion = aLayer->GetVisibleRegion(); |
michael@0 | 128 | |
michael@0 | 129 | uint32_t maxWidth = std::min<uint32_t>(visibleRegion.GetBounds().width, 500); |
michael@0 | 130 | |
michael@0 | 131 | nsIntPoint topLeft = visibleRegion.GetBounds().TopLeft(); |
michael@0 | 132 | aManager->GetTextRenderer()->RenderText(layerInfo.get(), gfx::IntPoint(topLeft.x, topLeft.y), |
michael@0 | 133 | aLayer->GetEffectiveTransform(), 16, |
michael@0 | 134 | maxWidth); |
michael@0 | 135 | |
michael@0 | 136 | } |
michael@0 | 137 | |
michael@0 | 138 | static LayerVelocityUserData* GetVelocityData(Layer* aLayer) { |
michael@0 | 139 | static char sLayerVelocityUserDataKey; |
michael@0 | 140 | void* key = reinterpret_cast<void*>(&sLayerVelocityUserDataKey); |
michael@0 | 141 | if (!aLayer->HasUserData(key)) { |
michael@0 | 142 | LayerVelocityUserData* newData = new LayerVelocityUserData(); |
michael@0 | 143 | aLayer->SetUserData(key, newData); |
michael@0 | 144 | } |
michael@0 | 145 | |
michael@0 | 146 | return static_cast<LayerVelocityUserData*>(aLayer->GetUserData(key)); |
michael@0 | 147 | } |
michael@0 | 148 | |
michael@0 | 149 | static void DrawVelGraph(const nsIntRect& aClipRect, |
michael@0 | 150 | LayerManagerComposite* aManager, |
michael@0 | 151 | Layer* aLayer) { |
michael@0 | 152 | Compositor* compositor = aManager->GetCompositor(); |
michael@0 | 153 | gfx::Rect clipRect(aClipRect.x, aClipRect.y, |
michael@0 | 154 | aClipRect.width, aClipRect.height); |
michael@0 | 155 | |
michael@0 | 156 | TimeStamp now = TimeStamp::Now(); |
michael@0 | 157 | LayerVelocityUserData* velocityData = GetVelocityData(aLayer); |
michael@0 | 158 | |
michael@0 | 159 | if (velocityData->mData.size() >= 1 && |
michael@0 | 160 | now > velocityData->mData[velocityData->mData.size() - 1].mFrameTime + |
michael@0 | 161 | TimeDuration::FromMilliseconds(200)) { |
michael@0 | 162 | // clear stale data |
michael@0 | 163 | velocityData->mData.clear(); |
michael@0 | 164 | } |
michael@0 | 165 | |
michael@0 | 166 | const gfx::Point layerTransform = GetScrollData(aLayer); |
michael@0 | 167 | velocityData->mData.push_back( |
michael@0 | 168 | LayerVelocityUserData::VelocityData(now, |
michael@0 | 169 | static_cast<int>(layerTransform.x), static_cast<int>(layerTransform.y))); |
michael@0 | 170 | |
michael@0 | 171 | // TODO: dump to file |
michael@0 | 172 | // XXX: Uncomment these lines to enable ScrollGraph logging. This is |
michael@0 | 173 | // useful for HVGA phones or to output the data to accurate |
michael@0 | 174 | // graphing software. |
michael@0 | 175 | // printf_stderr("ScrollGraph (%p): %f, %f\n", |
michael@0 | 176 | // aLayer, layerTransform.x, layerTransform.y); |
michael@0 | 177 | |
michael@0 | 178 | // Keep a circular buffer of 100. |
michael@0 | 179 | size_t circularBufferSize = 100; |
michael@0 | 180 | if (velocityData->mData.size() > circularBufferSize) { |
michael@0 | 181 | velocityData->mData.erase(velocityData->mData.begin()); |
michael@0 | 182 | } |
michael@0 | 183 | |
michael@0 | 184 | if (velocityData->mData.size() == 1) { |
michael@0 | 185 | return; |
michael@0 | 186 | } |
michael@0 | 187 | |
michael@0 | 188 | // Clear and disable the graph when it's flat |
michael@0 | 189 | for (size_t i = 1; i < velocityData->mData.size(); i++) { |
michael@0 | 190 | if (velocityData->mData[i - 1].mPoint != velocityData->mData[i].mPoint) { |
michael@0 | 191 | break; |
michael@0 | 192 | } |
michael@0 | 193 | if (i == velocityData->mData.size() - 1) { |
michael@0 | 194 | velocityData->mData.clear(); |
michael@0 | 195 | return; |
michael@0 | 196 | } |
michael@0 | 197 | } |
michael@0 | 198 | |
michael@0 | 199 | if (aLayer->GetEffectiveVisibleRegion().GetBounds().width < 300 || |
michael@0 | 200 | aLayer->GetEffectiveVisibleRegion().GetBounds().height < 300) { |
michael@0 | 201 | // Don't want a graph for smaller layers |
michael@0 | 202 | return; |
michael@0 | 203 | } |
michael@0 | 204 | |
michael@0 | 205 | aManager->SetDebugOverlayWantsNextFrame(true); |
michael@0 | 206 | |
michael@0 | 207 | const gfx::Matrix4x4& transform = aLayer->GetEffectiveTransform(); |
michael@0 | 208 | nsIntRect bounds = aLayer->GetEffectiveVisibleRegion().GetBounds(); |
michael@0 | 209 | gfx::Rect graphBounds = gfx::Rect(bounds.x, bounds.y, |
michael@0 | 210 | bounds.width, bounds.height); |
michael@0 | 211 | gfx::Rect graphRect = gfx::Rect(bounds.x, bounds.y, 200, 100); |
michael@0 | 212 | |
michael@0 | 213 | float opacity = 1.0; |
michael@0 | 214 | EffectChain effects; |
michael@0 | 215 | effects.mPrimaryEffect = new EffectSolidColor(gfx::Color(0.2f,0,0,1)); |
michael@0 | 216 | compositor->DrawQuad(graphRect, |
michael@0 | 217 | clipRect, |
michael@0 | 218 | effects, |
michael@0 | 219 | opacity, |
michael@0 | 220 | transform); |
michael@0 | 221 | |
michael@0 | 222 | std::vector<gfx::Point> graph; |
michael@0 | 223 | int yScaleFactor = 3; |
michael@0 | 224 | for (int32_t i = (int32_t)velocityData->mData.size() - 2; i >= 0; i--) { |
michael@0 | 225 | const gfx::Point& p1 = velocityData->mData[i+1].mPoint; |
michael@0 | 226 | const gfx::Point& p2 = velocityData->mData[i].mPoint; |
michael@0 | 227 | int vel = sqrt((p1.x - p2.x) * (p1.x - p2.x) + |
michael@0 | 228 | (p1.y - p2.y) * (p1.y - p2.y)); |
michael@0 | 229 | graph.push_back( |
michael@0 | 230 | gfx::Point(bounds.x + graphRect.width / circularBufferSize * i, |
michael@0 | 231 | graphBounds.y + graphRect.height - vel/yScaleFactor)); |
michael@0 | 232 | } |
michael@0 | 233 | |
michael@0 | 234 | compositor->DrawLines(graph, clipRect, gfx::Color(0,1,0,1), |
michael@0 | 235 | opacity, transform); |
michael@0 | 236 | } |
michael@0 | 237 | |
michael@0 | 238 | // ContainerRender is shared between RefLayer and ContainerLayer |
michael@0 | 239 | template<class ContainerT> void |
michael@0 | 240 | ContainerRender(ContainerT* aContainer, |
michael@0 | 241 | LayerManagerComposite* aManager, |
michael@0 | 242 | const nsIntRect& aClipRect) |
michael@0 | 243 | { |
michael@0 | 244 | /** |
michael@0 | 245 | * Setup our temporary surface for rendering the contents of this container. |
michael@0 | 246 | */ |
michael@0 | 247 | RefPtr<CompositingRenderTarget> surface; |
michael@0 | 248 | |
michael@0 | 249 | Compositor* compositor = aManager->GetCompositor(); |
michael@0 | 250 | |
michael@0 | 251 | RefPtr<CompositingRenderTarget> previousTarget = compositor->GetCurrentRenderTarget(); |
michael@0 | 252 | |
michael@0 | 253 | nsIntRect visibleRect = aContainer->GetEffectiveVisibleRegion().GetBounds(); |
michael@0 | 254 | |
michael@0 | 255 | aContainer->mSupportsComponentAlphaChildren = false; |
michael@0 | 256 | |
michael@0 | 257 | float opacity = aContainer->GetEffectiveOpacity(); |
michael@0 | 258 | |
michael@0 | 259 | bool needsSurface = aContainer->UseIntermediateSurface(); |
michael@0 | 260 | if (needsSurface) { |
michael@0 | 261 | SurfaceInitMode mode = INIT_MODE_CLEAR; |
michael@0 | 262 | bool surfaceCopyNeeded = false; |
michael@0 | 263 | gfx::IntRect surfaceRect = gfx::IntRect(visibleRect.x, visibleRect.y, |
michael@0 | 264 | visibleRect.width, visibleRect.height); |
michael@0 | 265 | gfx::IntPoint sourcePoint = gfx::IntPoint(visibleRect.x, visibleRect.y); |
michael@0 | 266 | // we're about to create a framebuffer backed by textures to use as an intermediate |
michael@0 | 267 | // surface. What to do if its size (as given by framebufferRect) would exceed the |
michael@0 | 268 | // maximum texture size supported by the GL? The present code chooses the compromise |
michael@0 | 269 | // of just clamping the framebuffer's size to the max supported size. |
michael@0 | 270 | // This gives us a lower resolution rendering of the intermediate surface (children layers). |
michael@0 | 271 | // See bug 827170 for a discussion. |
michael@0 | 272 | int32_t maxTextureSize = compositor->GetMaxTextureSize(); |
michael@0 | 273 | surfaceRect.width = std::min(maxTextureSize, surfaceRect.width); |
michael@0 | 274 | surfaceRect.height = std::min(maxTextureSize, surfaceRect.height); |
michael@0 | 275 | if (aContainer->GetEffectiveVisibleRegion().GetNumRects() == 1 && |
michael@0 | 276 | (aContainer->GetContentFlags() & Layer::CONTENT_OPAQUE)) |
michael@0 | 277 | { |
michael@0 | 278 | // don't need a background, we're going to paint all opaque stuff |
michael@0 | 279 | aContainer->mSupportsComponentAlphaChildren = true; |
michael@0 | 280 | mode = INIT_MODE_NONE; |
michael@0 | 281 | } else { |
michael@0 | 282 | const gfx::Matrix4x4& transform3D = aContainer->GetEffectiveTransform(); |
michael@0 | 283 | gfx::Matrix transform; |
michael@0 | 284 | // If we have an opaque ancestor layer, then we can be sure that |
michael@0 | 285 | // all the pixels we draw into are either opaque already or will be |
michael@0 | 286 | // covered by something opaque. Otherwise copying up the background is |
michael@0 | 287 | // not safe. |
michael@0 | 288 | if (ContainerLayer::HasOpaqueAncestorLayer(aContainer) && |
michael@0 | 289 | transform3D.Is2D(&transform) && !ThebesMatrix(transform).HasNonIntegerTranslation()) { |
michael@0 | 290 | surfaceCopyNeeded = gfxPrefs::ComponentAlphaEnabled(); |
michael@0 | 291 | sourcePoint.x += transform._31; |
michael@0 | 292 | sourcePoint.y += transform._32; |
michael@0 | 293 | aContainer->mSupportsComponentAlphaChildren |
michael@0 | 294 | = gfxPrefs::ComponentAlphaEnabled(); |
michael@0 | 295 | } |
michael@0 | 296 | } |
michael@0 | 297 | |
michael@0 | 298 | sourcePoint -= compositor->GetCurrentRenderTarget()->GetOrigin(); |
michael@0 | 299 | if (surfaceCopyNeeded) { |
michael@0 | 300 | surface = compositor->CreateRenderTargetFromSource(surfaceRect, previousTarget, sourcePoint); |
michael@0 | 301 | } else { |
michael@0 | 302 | surface = compositor->CreateRenderTarget(surfaceRect, mode); |
michael@0 | 303 | } |
michael@0 | 304 | |
michael@0 | 305 | if (!surface) { |
michael@0 | 306 | return; |
michael@0 | 307 | } |
michael@0 | 308 | |
michael@0 | 309 | compositor->SetRenderTarget(surface); |
michael@0 | 310 | } else { |
michael@0 | 311 | surface = previousTarget; |
michael@0 | 312 | aContainer->mSupportsComponentAlphaChildren = (aContainer->GetContentFlags() & Layer::CONTENT_OPAQUE) || |
michael@0 | 313 | (aContainer->GetParent() && aContainer->GetParent()->SupportsComponentAlphaChildren()); |
michael@0 | 314 | } |
michael@0 | 315 | |
michael@0 | 316 | nsAutoTArray<Layer*, 12> children; |
michael@0 | 317 | aContainer->SortChildrenBy3DZOrder(children); |
michael@0 | 318 | |
michael@0 | 319 | /** |
michael@0 | 320 | * Render this container's contents. |
michael@0 | 321 | */ |
michael@0 | 322 | for (uint32_t i = 0; i < children.Length(); i++) { |
michael@0 | 323 | LayerComposite* layerToRender = static_cast<LayerComposite*>(children.ElementAt(i)->ImplData()); |
michael@0 | 324 | |
michael@0 | 325 | if (layerToRender->GetLayer()->GetEffectiveVisibleRegion().IsEmpty() && |
michael@0 | 326 | !layerToRender->GetLayer()->AsContainerLayer()) { |
michael@0 | 327 | continue; |
michael@0 | 328 | } |
michael@0 | 329 | |
michael@0 | 330 | nsIntRect clipRect = layerToRender->GetLayer()-> |
michael@0 | 331 | CalculateScissorRect(aClipRect, &aManager->GetWorldTransform()); |
michael@0 | 332 | if (clipRect.IsEmpty()) { |
michael@0 | 333 | continue; |
michael@0 | 334 | } |
michael@0 | 335 | |
michael@0 | 336 | nsIntRegion savedVisibleRegion; |
michael@0 | 337 | bool restoreVisibleRegion = false; |
michael@0 | 338 | if (i + 1 < children.Length() && |
michael@0 | 339 | layerToRender->GetLayer()->GetEffectiveTransform().IsIdentity()) { |
michael@0 | 340 | LayerComposite* nextLayer = static_cast<LayerComposite*>(children.ElementAt(i + 1)->ImplData()); |
michael@0 | 341 | nsIntRect nextLayerOpaqueRect; |
michael@0 | 342 | if (nextLayer && nextLayer->GetLayer()) { |
michael@0 | 343 | nextLayerOpaqueRect = GetOpaqueRect(nextLayer->GetLayer()); |
michael@0 | 344 | } |
michael@0 | 345 | if (!nextLayerOpaqueRect.IsEmpty()) { |
michael@0 | 346 | savedVisibleRegion = layerToRender->GetShadowVisibleRegion(); |
michael@0 | 347 | nsIntRegion visibleRegion; |
michael@0 | 348 | visibleRegion.Sub(savedVisibleRegion, nextLayerOpaqueRect); |
michael@0 | 349 | if (visibleRegion.IsEmpty()) { |
michael@0 | 350 | continue; |
michael@0 | 351 | } |
michael@0 | 352 | layerToRender->SetShadowVisibleRegion(visibleRegion); |
michael@0 | 353 | restoreVisibleRegion = true; |
michael@0 | 354 | } |
michael@0 | 355 | } |
michael@0 | 356 | |
michael@0 | 357 | if (layerToRender->HasLayerBeenComposited()) { |
michael@0 | 358 | // Composer2D will compose this layer so skip GPU composition |
michael@0 | 359 | // this time & reset composition flag for next composition phase |
michael@0 | 360 | layerToRender->SetLayerComposited(false); |
michael@0 | 361 | nsIntRect clearRect = layerToRender->GetClearRect(); |
michael@0 | 362 | if (!clearRect.IsEmpty()) { |
michael@0 | 363 | // Clear layer's visible rect on FrameBuffer with transparent pixels |
michael@0 | 364 | gfx::Rect fbRect(clearRect.x, clearRect.y, clearRect.width, clearRect.height); |
michael@0 | 365 | compositor->ClearRect(fbRect); |
michael@0 | 366 | layerToRender->SetClearRect(nsIntRect(0, 0, 0, 0)); |
michael@0 | 367 | } |
michael@0 | 368 | } else { |
michael@0 | 369 | layerToRender->RenderLayer(clipRect); |
michael@0 | 370 | } |
michael@0 | 371 | |
michael@0 | 372 | if (restoreVisibleRegion) { |
michael@0 | 373 | // Restore the region in case it's not covered by opaque content next time |
michael@0 | 374 | layerToRender->SetShadowVisibleRegion(savedVisibleRegion); |
michael@0 | 375 | } |
michael@0 | 376 | |
michael@0 | 377 | if (gfxPrefs::LayersScrollGraph()) { |
michael@0 | 378 | DrawVelGraph(clipRect, aManager, layerToRender->GetLayer()); |
michael@0 | 379 | } |
michael@0 | 380 | |
michael@0 | 381 | if (gfxPrefs::DrawLayerInfo()) { |
michael@0 | 382 | DrawLayerInfo(clipRect, aManager, layerToRender->GetLayer()); |
michael@0 | 383 | } |
michael@0 | 384 | // invariant: our GL context should be current here, I don't think we can |
michael@0 | 385 | // assert it though |
michael@0 | 386 | } |
michael@0 | 387 | |
michael@0 | 388 | if (needsSurface) { |
michael@0 | 389 | // Unbind the current surface and rebind the previous one. |
michael@0 | 390 | #ifdef MOZ_DUMP_PAINTING |
michael@0 | 391 | if (gfxUtils::sDumpPainting) { |
michael@0 | 392 | RefPtr<gfx::DataSourceSurface> surf = surface->Dump(aManager->GetCompositor()); |
michael@0 | 393 | WriteSnapshotToDumpFile(aContainer, surf); |
michael@0 | 394 | } |
michael@0 | 395 | #endif |
michael@0 | 396 | |
michael@0 | 397 | compositor->SetRenderTarget(previousTarget); |
michael@0 | 398 | EffectChain effectChain(aContainer); |
michael@0 | 399 | LayerManagerComposite::AutoAddMaskEffect autoMaskEffect(aContainer->GetMaskLayer(), |
michael@0 | 400 | effectChain, |
michael@0 | 401 | !aContainer->GetTransform().CanDraw2D()); |
michael@0 | 402 | |
michael@0 | 403 | effectChain.mPrimaryEffect = new EffectRenderTarget(surface); |
michael@0 | 404 | |
michael@0 | 405 | gfx::Rect rect(visibleRect.x, visibleRect.y, visibleRect.width, visibleRect.height); |
michael@0 | 406 | gfx::Rect clipRect(aClipRect.x, aClipRect.y, aClipRect.width, aClipRect.height); |
michael@0 | 407 | aManager->GetCompositor()->DrawQuad(rect, clipRect, effectChain, opacity, |
michael@0 | 408 | aContainer->GetEffectiveTransform()); |
michael@0 | 409 | } |
michael@0 | 410 | |
michael@0 | 411 | if (aContainer->GetFrameMetrics().IsScrollable()) { |
michael@0 | 412 | const FrameMetrics& frame = aContainer->GetFrameMetrics(); |
michael@0 | 413 | LayerRect layerBounds = ParentLayerRect(frame.mCompositionBounds) * ParentLayerToLayerScale(1.0); |
michael@0 | 414 | gfx::Rect rect(layerBounds.x, layerBounds.y, layerBounds.width, layerBounds.height); |
michael@0 | 415 | gfx::Rect clipRect(aClipRect.x, aClipRect.y, aClipRect.width, aClipRect.height); |
michael@0 | 416 | aManager->GetCompositor()->DrawDiagnostics(DIAGNOSTIC_CONTAINER, |
michael@0 | 417 | rect, clipRect, |
michael@0 | 418 | aContainer->GetEffectiveTransform()); |
michael@0 | 419 | } |
michael@0 | 420 | } |
michael@0 | 421 | |
michael@0 | 422 | ContainerLayerComposite::ContainerLayerComposite(LayerManagerComposite *aManager) |
michael@0 | 423 | : ContainerLayer(aManager, nullptr) |
michael@0 | 424 | , LayerComposite(aManager) |
michael@0 | 425 | { |
michael@0 | 426 | MOZ_COUNT_CTOR(ContainerLayerComposite); |
michael@0 | 427 | mImplData = static_cast<LayerComposite*>(this); |
michael@0 | 428 | } |
michael@0 | 429 | |
michael@0 | 430 | ContainerLayerComposite::~ContainerLayerComposite() |
michael@0 | 431 | { |
michael@0 | 432 | MOZ_COUNT_DTOR(ContainerLayerComposite); |
michael@0 | 433 | |
michael@0 | 434 | // We don't Destroy() on destruction here because this destructor |
michael@0 | 435 | // can be called after remote content has crashed, and it may not be |
michael@0 | 436 | // safe to free the IPC resources of our children. Those resources |
michael@0 | 437 | // are automatically cleaned up by IPDL-generated code. |
michael@0 | 438 | // |
michael@0 | 439 | // In the common case of normal shutdown, either |
michael@0 | 440 | // LayerManagerComposite::Destroy(), a parent |
michael@0 | 441 | // *ContainerLayerComposite::Destroy(), or Disconnect() will trigger |
michael@0 | 442 | // cleanup of our resources. |
michael@0 | 443 | while (mFirstChild) { |
michael@0 | 444 | RemoveChild(mFirstChild); |
michael@0 | 445 | } |
michael@0 | 446 | } |
michael@0 | 447 | |
michael@0 | 448 | void |
michael@0 | 449 | ContainerLayerComposite::Destroy() |
michael@0 | 450 | { |
michael@0 | 451 | if (!mDestroyed) { |
michael@0 | 452 | while (mFirstChild) { |
michael@0 | 453 | static_cast<LayerComposite*>(GetFirstChild()->ImplData())->Destroy(); |
michael@0 | 454 | RemoveChild(mFirstChild); |
michael@0 | 455 | } |
michael@0 | 456 | mDestroyed = true; |
michael@0 | 457 | } |
michael@0 | 458 | } |
michael@0 | 459 | |
michael@0 | 460 | LayerComposite* |
michael@0 | 461 | ContainerLayerComposite::GetFirstChildComposite() |
michael@0 | 462 | { |
michael@0 | 463 | if (!mFirstChild) { |
michael@0 | 464 | return nullptr; |
michael@0 | 465 | } |
michael@0 | 466 | return static_cast<LayerComposite*>(mFirstChild->ImplData()); |
michael@0 | 467 | } |
michael@0 | 468 | |
michael@0 | 469 | void |
michael@0 | 470 | ContainerLayerComposite::RenderLayer(const nsIntRect& aClipRect) |
michael@0 | 471 | { |
michael@0 | 472 | ContainerRender(this, mCompositeManager, aClipRect); |
michael@0 | 473 | } |
michael@0 | 474 | |
michael@0 | 475 | void |
michael@0 | 476 | ContainerLayerComposite::CleanupResources() |
michael@0 | 477 | { |
michael@0 | 478 | for (Layer* l = GetFirstChild(); l; l = l->GetNextSibling()) { |
michael@0 | 479 | LayerComposite* layerToCleanup = static_cast<LayerComposite*>(l->ImplData()); |
michael@0 | 480 | layerToCleanup->CleanupResources(); |
michael@0 | 481 | } |
michael@0 | 482 | } |
michael@0 | 483 | |
michael@0 | 484 | RefLayerComposite::RefLayerComposite(LayerManagerComposite* aManager) |
michael@0 | 485 | : RefLayer(aManager, nullptr) |
michael@0 | 486 | , LayerComposite(aManager) |
michael@0 | 487 | { |
michael@0 | 488 | mImplData = static_cast<LayerComposite*>(this); |
michael@0 | 489 | } |
michael@0 | 490 | |
michael@0 | 491 | RefLayerComposite::~RefLayerComposite() |
michael@0 | 492 | { |
michael@0 | 493 | Destroy(); |
michael@0 | 494 | } |
michael@0 | 495 | |
michael@0 | 496 | void |
michael@0 | 497 | RefLayerComposite::Destroy() |
michael@0 | 498 | { |
michael@0 | 499 | MOZ_ASSERT(!mFirstChild); |
michael@0 | 500 | mDestroyed = true; |
michael@0 | 501 | } |
michael@0 | 502 | |
michael@0 | 503 | LayerComposite* |
michael@0 | 504 | RefLayerComposite::GetFirstChildComposite() |
michael@0 | 505 | { |
michael@0 | 506 | if (!mFirstChild) { |
michael@0 | 507 | return nullptr; |
michael@0 | 508 | } |
michael@0 | 509 | return static_cast<LayerComposite*>(mFirstChild->ImplData()); |
michael@0 | 510 | } |
michael@0 | 511 | |
michael@0 | 512 | void |
michael@0 | 513 | RefLayerComposite::RenderLayer(const nsIntRect& aClipRect) |
michael@0 | 514 | { |
michael@0 | 515 | ContainerRender(this, mCompositeManager, aClipRect); |
michael@0 | 516 | } |
michael@0 | 517 | |
michael@0 | 518 | void |
michael@0 | 519 | RefLayerComposite::CleanupResources() |
michael@0 | 520 | { |
michael@0 | 521 | } |
michael@0 | 522 | |
michael@0 | 523 | } /* layers */ |
michael@0 | 524 | } /* mozilla */ |