gfx/layers/composite/ContainerLayerComposite.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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 */

mercurial