gfx/layers/composite/ContainerLayerComposite.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/layers/composite/ContainerLayerComposite.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,524 @@
     1.4 +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
     1.5 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#include "ContainerLayerComposite.h"
    1.10 +#include <algorithm>                    // for min
    1.11 +#include "FrameMetrics.h"               // for FrameMetrics
    1.12 +#include "Units.h"                      // for LayerRect, LayerPixel, etc
    1.13 +#include "gfx2DGlue.h"                  // for ToMatrix4x4
    1.14 +#include "gfx3DMatrix.h"                // for gfx3DMatrix
    1.15 +#include "gfxPrefs.h"                   // for gfxPrefs
    1.16 +#include "gfxUtils.h"                   // for gfxUtils, etc
    1.17 +#include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
    1.18 +#include "mozilla/RefPtr.h"             // for RefPtr
    1.19 +#include "mozilla/gfx/BaseRect.h"       // for BaseRect
    1.20 +#include "mozilla/gfx/Matrix.h"         // for Matrix4x4
    1.21 +#include "mozilla/gfx/Point.h"          // for Point, IntPoint
    1.22 +#include "mozilla/gfx/Rect.h"           // for IntRect, Rect
    1.23 +#include "mozilla/layers/Compositor.h"  // for Compositor, etc
    1.24 +#include "mozilla/layers/CompositorTypes.h"  // for DIAGNOSTIC_CONTAINER
    1.25 +#include "mozilla/layers/Effects.h"     // for Effect, EffectChain, etc
    1.26 +#include "mozilla/layers/TextureHost.h"  // for CompositingRenderTarget
    1.27 +#include "mozilla/mozalloc.h"           // for operator delete, etc
    1.28 +#include "nsAutoPtr.h"                  // for nsRefPtr
    1.29 +#include "nsDebug.h"                    // for NS_ASSERTION
    1.30 +#include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
    1.31 +#include "nsISupportsUtils.h"           // for NS_ADDREF, NS_RELEASE
    1.32 +#include "nsPoint.h"                    // for nsIntPoint
    1.33 +#include "nsRect.h"                     // for nsIntRect
    1.34 +#include "nsRegion.h"                   // for nsIntRegion
    1.35 +#include "nsTArray.h"                   // for nsAutoTArray
    1.36 +#include "TextRenderer.h"               // for TextRenderer
    1.37 +#include <vector>
    1.38 +
    1.39 +namespace mozilla {
    1.40 +namespace layers {
    1.41 +
    1.42 +/**
    1.43 + * Returns a rectangle of content painted opaquely by aLayer. Very consertative;
    1.44 + * bails by returning an empty rect in any tricky situations.
    1.45 + */
    1.46 +static nsIntRect
    1.47 +GetOpaqueRect(Layer* aLayer)
    1.48 +{
    1.49 +  nsIntRect result;
    1.50 +  gfx::Matrix matrix;
    1.51 +  bool is2D = aLayer->GetBaseTransform().Is2D(&matrix);
    1.52 +
    1.53 +  // Just bail if there's anything difficult to handle.
    1.54 +  if (!is2D || aLayer->GetMaskLayer() ||
    1.55 +    aLayer->GetEffectiveOpacity() != 1.0f ||
    1.56 +    matrix.HasNonIntegerTranslation()) {
    1.57 +    return result;
    1.58 +  }
    1.59 +
    1.60 +  if (aLayer->GetContentFlags() & Layer::CONTENT_OPAQUE) {
    1.61 +    result = aLayer->GetEffectiveVisibleRegion().GetLargestRectangle();
    1.62 +  } else {
    1.63 +    // Drill down into RefLayers because that's what we particularly care about;
    1.64 +    // layer construction for aLayer will not have known about the opaqueness
    1.65 +    // of any RefLayer subtrees.
    1.66 +    RefLayer* refLayer = aLayer->AsRefLayer();
    1.67 +    if (refLayer && refLayer->GetFirstChild()) {
    1.68 +      result = GetOpaqueRect(refLayer->GetFirstChild());
    1.69 +    }
    1.70 +  }
    1.71 +
    1.72 +  // Translate our opaque region to cover the child
    1.73 +  gfx::Point point = matrix.GetTranslation();
    1.74 +  result.MoveBy(static_cast<int>(point.x), static_cast<int>(point.y));
    1.75 +
    1.76 +  const nsIntRect* clipRect = aLayer->GetEffectiveClipRect();
    1.77 +  if (clipRect) {
    1.78 +    result.IntersectRect(result, *clipRect);
    1.79 +  }
    1.80 +
    1.81 +  return result;
    1.82 +}
    1.83 +
    1.84 +struct LayerVelocityUserData : public LayerUserData {
    1.85 +public:
    1.86 +  LayerVelocityUserData() {
    1.87 +    MOZ_COUNT_CTOR(LayerVelocityUserData);
    1.88 +  }
    1.89 +  ~LayerVelocityUserData() {
    1.90 +    MOZ_COUNT_DTOR(LayerVelocityUserData);
    1.91 +  }
    1.92 +
    1.93 +  struct VelocityData {
    1.94 +    VelocityData(TimeStamp frameTime, int scrollX, int scrollY)
    1.95 +      : mFrameTime(frameTime)
    1.96 +      , mPoint(scrollX, scrollY)
    1.97 +    {}
    1.98 +
    1.99 +    TimeStamp mFrameTime;
   1.100 +    gfx::Point mPoint;
   1.101 +  };
   1.102 +  std::vector<VelocityData> mData;
   1.103 +};
   1.104 +
   1.105 +static gfx::Point GetScrollData(Layer* aLayer) {
   1.106 +  gfx::Matrix matrix;
   1.107 +  if (aLayer->GetLocalTransform().Is2D(&matrix)) {
   1.108 +    return matrix.GetTranslation();
   1.109 +  }
   1.110 +
   1.111 +  gfx::Point origin;
   1.112 +  return origin;
   1.113 +}
   1.114 +
   1.115 +static void DrawLayerInfo(const nsIntRect& aClipRect,
   1.116 +                          LayerManagerComposite* aManager,
   1.117 +                          Layer* aLayer)
   1.118 +{
   1.119 +
   1.120 +  if (aLayer->GetType() == Layer::LayerType::TYPE_CONTAINER) {
   1.121 +    // XXX - should figure out a way to render this, but for now this
   1.122 +    // is hard to do, since it will often get superimposed over the first
   1.123 +    // child of the layer, which is bad.
   1.124 +    return;
   1.125 +  }
   1.126 +
   1.127 +  nsAutoCString layerInfo;
   1.128 +  aLayer->PrintInfo(layerInfo, "");
   1.129 +
   1.130 +  nsIntRegion visibleRegion = aLayer->GetVisibleRegion();
   1.131 +
   1.132 +  uint32_t maxWidth = std::min<uint32_t>(visibleRegion.GetBounds().width, 500);
   1.133 +
   1.134 +  nsIntPoint topLeft = visibleRegion.GetBounds().TopLeft();
   1.135 +  aManager->GetTextRenderer()->RenderText(layerInfo.get(), gfx::IntPoint(topLeft.x, topLeft.y),
   1.136 +                                          aLayer->GetEffectiveTransform(), 16,
   1.137 +                                          maxWidth);
   1.138 +
   1.139 +}
   1.140 +
   1.141 +static LayerVelocityUserData* GetVelocityData(Layer* aLayer) {
   1.142 +  static char sLayerVelocityUserDataKey;
   1.143 +  void* key = reinterpret_cast<void*>(&sLayerVelocityUserDataKey);
   1.144 +  if (!aLayer->HasUserData(key)) {
   1.145 +    LayerVelocityUserData* newData = new LayerVelocityUserData();
   1.146 +    aLayer->SetUserData(key, newData);
   1.147 +  }
   1.148 +
   1.149 +  return static_cast<LayerVelocityUserData*>(aLayer->GetUserData(key));
   1.150 +}
   1.151 +
   1.152 +static void DrawVelGraph(const nsIntRect& aClipRect,
   1.153 +                         LayerManagerComposite* aManager,
   1.154 +                         Layer* aLayer) {
   1.155 +  Compositor* compositor = aManager->GetCompositor();
   1.156 +  gfx::Rect clipRect(aClipRect.x, aClipRect.y,
   1.157 +                     aClipRect.width, aClipRect.height);
   1.158 +
   1.159 +  TimeStamp now = TimeStamp::Now();
   1.160 +  LayerVelocityUserData* velocityData = GetVelocityData(aLayer);
   1.161 +
   1.162 +  if (velocityData->mData.size() >= 1 &&
   1.163 +    now > velocityData->mData[velocityData->mData.size() - 1].mFrameTime +
   1.164 +      TimeDuration::FromMilliseconds(200)) {
   1.165 +    // clear stale data
   1.166 +    velocityData->mData.clear();
   1.167 +  }
   1.168 +
   1.169 +  const gfx::Point layerTransform = GetScrollData(aLayer);
   1.170 +  velocityData->mData.push_back(
   1.171 +    LayerVelocityUserData::VelocityData(now,
   1.172 +      static_cast<int>(layerTransform.x), static_cast<int>(layerTransform.y)));
   1.173 +
   1.174 +  // TODO: dump to file
   1.175 +  // XXX: Uncomment these lines to enable ScrollGraph logging. This is
   1.176 +  //      useful for HVGA phones or to output the data to accurate
   1.177 +  //      graphing software.
   1.178 +  // printf_stderr("ScrollGraph (%p): %f, %f\n",
   1.179 +  // aLayer, layerTransform.x, layerTransform.y);
   1.180 +
   1.181 +  // Keep a circular buffer of 100.
   1.182 +  size_t circularBufferSize = 100;
   1.183 +  if (velocityData->mData.size() > circularBufferSize) {
   1.184 +    velocityData->mData.erase(velocityData->mData.begin());
   1.185 +  }
   1.186 +
   1.187 +  if (velocityData->mData.size() == 1) {
   1.188 +    return;
   1.189 +  }
   1.190 +
   1.191 +  // Clear and disable the graph when it's flat
   1.192 +  for (size_t i = 1; i < velocityData->mData.size(); i++) {
   1.193 +    if (velocityData->mData[i - 1].mPoint != velocityData->mData[i].mPoint) {
   1.194 +      break;
   1.195 +    }
   1.196 +    if (i == velocityData->mData.size() - 1) {
   1.197 +      velocityData->mData.clear();
   1.198 +      return;
   1.199 +    }
   1.200 +  }
   1.201 +
   1.202 +  if (aLayer->GetEffectiveVisibleRegion().GetBounds().width < 300 ||
   1.203 +      aLayer->GetEffectiveVisibleRegion().GetBounds().height < 300) {
   1.204 +    // Don't want a graph for smaller layers
   1.205 +    return;
   1.206 +  }
   1.207 +
   1.208 +  aManager->SetDebugOverlayWantsNextFrame(true);
   1.209 +
   1.210 +  const gfx::Matrix4x4& transform = aLayer->GetEffectiveTransform();
   1.211 +  nsIntRect bounds = aLayer->GetEffectiveVisibleRegion().GetBounds();
   1.212 +  gfx::Rect graphBounds = gfx::Rect(bounds.x, bounds.y,
   1.213 +                                    bounds.width, bounds.height);
   1.214 +  gfx::Rect graphRect = gfx::Rect(bounds.x, bounds.y, 200, 100);
   1.215 +
   1.216 +  float opacity = 1.0;
   1.217 +  EffectChain effects;
   1.218 +  effects.mPrimaryEffect = new EffectSolidColor(gfx::Color(0.2f,0,0,1));
   1.219 +  compositor->DrawQuad(graphRect,
   1.220 +                       clipRect,
   1.221 +                       effects,
   1.222 +                       opacity,
   1.223 +                       transform);
   1.224 +
   1.225 +  std::vector<gfx::Point> graph;
   1.226 +  int yScaleFactor = 3;
   1.227 +  for (int32_t i = (int32_t)velocityData->mData.size() - 2; i >= 0; i--) {
   1.228 +    const gfx::Point& p1 = velocityData->mData[i+1].mPoint;
   1.229 +    const gfx::Point& p2 = velocityData->mData[i].mPoint;
   1.230 +    int vel = sqrt((p1.x - p2.x) * (p1.x - p2.x) +
   1.231 +                   (p1.y - p2.y) * (p1.y - p2.y));
   1.232 +    graph.push_back(
   1.233 +      gfx::Point(bounds.x + graphRect.width / circularBufferSize * i,
   1.234 +                 graphBounds.y + graphRect.height - vel/yScaleFactor));
   1.235 +  }
   1.236 +
   1.237 +  compositor->DrawLines(graph, clipRect, gfx::Color(0,1,0,1),
   1.238 +                        opacity, transform);
   1.239 +}
   1.240 +
   1.241 +// ContainerRender is shared between RefLayer and ContainerLayer
   1.242 +template<class ContainerT> void
   1.243 +ContainerRender(ContainerT* aContainer,
   1.244 +                LayerManagerComposite* aManager,
   1.245 +                const nsIntRect& aClipRect)
   1.246 +{
   1.247 +  /**
   1.248 +   * Setup our temporary surface for rendering the contents of this container.
   1.249 +   */
   1.250 +  RefPtr<CompositingRenderTarget> surface;
   1.251 +
   1.252 +  Compositor* compositor = aManager->GetCompositor();
   1.253 +
   1.254 +  RefPtr<CompositingRenderTarget> previousTarget = compositor->GetCurrentRenderTarget();
   1.255 +
   1.256 +  nsIntRect visibleRect = aContainer->GetEffectiveVisibleRegion().GetBounds();
   1.257 +
   1.258 +  aContainer->mSupportsComponentAlphaChildren = false;
   1.259 +
   1.260 +  float opacity = aContainer->GetEffectiveOpacity();
   1.261 +
   1.262 +  bool needsSurface = aContainer->UseIntermediateSurface();
   1.263 +  if (needsSurface) {
   1.264 +    SurfaceInitMode mode = INIT_MODE_CLEAR;
   1.265 +    bool surfaceCopyNeeded = false;
   1.266 +    gfx::IntRect surfaceRect = gfx::IntRect(visibleRect.x, visibleRect.y,
   1.267 +                                            visibleRect.width, visibleRect.height);
   1.268 +    gfx::IntPoint sourcePoint = gfx::IntPoint(visibleRect.x, visibleRect.y);
   1.269 +    // we're about to create a framebuffer backed by textures to use as an intermediate
   1.270 +    // surface. What to do if its size (as given by framebufferRect) would exceed the
   1.271 +    // maximum texture size supported by the GL? The present code chooses the compromise
   1.272 +    // of just clamping the framebuffer's size to the max supported size.
   1.273 +    // This gives us a lower resolution rendering of the intermediate surface (children layers).
   1.274 +    // See bug 827170 for a discussion.
   1.275 +    int32_t maxTextureSize = compositor->GetMaxTextureSize();
   1.276 +    surfaceRect.width = std::min(maxTextureSize, surfaceRect.width);
   1.277 +    surfaceRect.height = std::min(maxTextureSize, surfaceRect.height);
   1.278 +    if (aContainer->GetEffectiveVisibleRegion().GetNumRects() == 1 &&
   1.279 +        (aContainer->GetContentFlags() & Layer::CONTENT_OPAQUE))
   1.280 +    {
   1.281 +      // don't need a background, we're going to paint all opaque stuff
   1.282 +      aContainer->mSupportsComponentAlphaChildren = true;
   1.283 +      mode = INIT_MODE_NONE;
   1.284 +    } else {
   1.285 +      const gfx::Matrix4x4& transform3D = aContainer->GetEffectiveTransform();
   1.286 +      gfx::Matrix transform;
   1.287 +      // If we have an opaque ancestor layer, then we can be sure that
   1.288 +      // all the pixels we draw into are either opaque already or will be
   1.289 +      // covered by something opaque. Otherwise copying up the background is
   1.290 +      // not safe.
   1.291 +      if (ContainerLayer::HasOpaqueAncestorLayer(aContainer) &&
   1.292 +          transform3D.Is2D(&transform) && !ThebesMatrix(transform).HasNonIntegerTranslation()) {
   1.293 +        surfaceCopyNeeded = gfxPrefs::ComponentAlphaEnabled();
   1.294 +        sourcePoint.x += transform._31;
   1.295 +        sourcePoint.y += transform._32;
   1.296 +        aContainer->mSupportsComponentAlphaChildren
   1.297 +          = gfxPrefs::ComponentAlphaEnabled();
   1.298 +      }
   1.299 +    }
   1.300 +
   1.301 +    sourcePoint -= compositor->GetCurrentRenderTarget()->GetOrigin();
   1.302 +    if (surfaceCopyNeeded) {
   1.303 +      surface = compositor->CreateRenderTargetFromSource(surfaceRect, previousTarget, sourcePoint);
   1.304 +    } else {
   1.305 +      surface = compositor->CreateRenderTarget(surfaceRect, mode);
   1.306 +    }
   1.307 +
   1.308 +    if (!surface) {
   1.309 +      return;
   1.310 +    }
   1.311 +
   1.312 +    compositor->SetRenderTarget(surface);
   1.313 +  } else {
   1.314 +    surface = previousTarget;
   1.315 +    aContainer->mSupportsComponentAlphaChildren = (aContainer->GetContentFlags() & Layer::CONTENT_OPAQUE) ||
   1.316 +      (aContainer->GetParent() && aContainer->GetParent()->SupportsComponentAlphaChildren());
   1.317 +  }
   1.318 +
   1.319 +  nsAutoTArray<Layer*, 12> children;
   1.320 +  aContainer->SortChildrenBy3DZOrder(children);
   1.321 +
   1.322 +  /**
   1.323 +   * Render this container's contents.
   1.324 +   */
   1.325 +  for (uint32_t i = 0; i < children.Length(); i++) {
   1.326 +    LayerComposite* layerToRender = static_cast<LayerComposite*>(children.ElementAt(i)->ImplData());
   1.327 +
   1.328 +    if (layerToRender->GetLayer()->GetEffectiveVisibleRegion().IsEmpty() &&
   1.329 +        !layerToRender->GetLayer()->AsContainerLayer()) {
   1.330 +      continue;
   1.331 +    }
   1.332 +
   1.333 +    nsIntRect clipRect = layerToRender->GetLayer()->
   1.334 +        CalculateScissorRect(aClipRect, &aManager->GetWorldTransform());
   1.335 +    if (clipRect.IsEmpty()) {
   1.336 +      continue;
   1.337 +    }
   1.338 +
   1.339 +    nsIntRegion savedVisibleRegion;
   1.340 +    bool restoreVisibleRegion = false;
   1.341 +    if (i + 1 < children.Length() &&
   1.342 +        layerToRender->GetLayer()->GetEffectiveTransform().IsIdentity()) {
   1.343 +      LayerComposite* nextLayer = static_cast<LayerComposite*>(children.ElementAt(i + 1)->ImplData());
   1.344 +      nsIntRect nextLayerOpaqueRect;
   1.345 +      if (nextLayer && nextLayer->GetLayer()) {
   1.346 +        nextLayerOpaqueRect = GetOpaqueRect(nextLayer->GetLayer());
   1.347 +      }
   1.348 +      if (!nextLayerOpaqueRect.IsEmpty()) {
   1.349 +        savedVisibleRegion = layerToRender->GetShadowVisibleRegion();
   1.350 +        nsIntRegion visibleRegion;
   1.351 +        visibleRegion.Sub(savedVisibleRegion, nextLayerOpaqueRect);
   1.352 +        if (visibleRegion.IsEmpty()) {
   1.353 +          continue;
   1.354 +        }
   1.355 +        layerToRender->SetShadowVisibleRegion(visibleRegion);
   1.356 +        restoreVisibleRegion = true;
   1.357 +      }
   1.358 +    }
   1.359 +
   1.360 +    if (layerToRender->HasLayerBeenComposited()) {
   1.361 +      // Composer2D will compose this layer so skip GPU composition
   1.362 +      // this time & reset composition flag for next composition phase
   1.363 +      layerToRender->SetLayerComposited(false);
   1.364 +      nsIntRect clearRect = layerToRender->GetClearRect();
   1.365 +      if (!clearRect.IsEmpty()) {
   1.366 +        // Clear layer's visible rect on FrameBuffer with transparent pixels
   1.367 +        gfx::Rect fbRect(clearRect.x, clearRect.y, clearRect.width, clearRect.height);
   1.368 +        compositor->ClearRect(fbRect);
   1.369 +        layerToRender->SetClearRect(nsIntRect(0, 0, 0, 0));
   1.370 +      }
   1.371 +    } else {
   1.372 +      layerToRender->RenderLayer(clipRect);
   1.373 +    }
   1.374 +
   1.375 +    if (restoreVisibleRegion) {
   1.376 +      // Restore the region in case it's not covered by opaque content next time
   1.377 +      layerToRender->SetShadowVisibleRegion(savedVisibleRegion);
   1.378 +    }
   1.379 +
   1.380 +    if (gfxPrefs::LayersScrollGraph()) {
   1.381 +      DrawVelGraph(clipRect, aManager, layerToRender->GetLayer());
   1.382 +    }
   1.383 +
   1.384 +    if (gfxPrefs::DrawLayerInfo()) {
   1.385 +      DrawLayerInfo(clipRect, aManager, layerToRender->GetLayer());
   1.386 +    }
   1.387 +    // invariant: our GL context should be current here, I don't think we can
   1.388 +    // assert it though
   1.389 +  }
   1.390 +
   1.391 +  if (needsSurface) {
   1.392 +    // Unbind the current surface and rebind the previous one.
   1.393 +#ifdef MOZ_DUMP_PAINTING
   1.394 +    if (gfxUtils::sDumpPainting) {
   1.395 +      RefPtr<gfx::DataSourceSurface> surf = surface->Dump(aManager->GetCompositor());
   1.396 +      WriteSnapshotToDumpFile(aContainer, surf);
   1.397 +    }
   1.398 +#endif
   1.399 +
   1.400 +    compositor->SetRenderTarget(previousTarget);
   1.401 +    EffectChain effectChain(aContainer);
   1.402 +    LayerManagerComposite::AutoAddMaskEffect autoMaskEffect(aContainer->GetMaskLayer(),
   1.403 +                                                            effectChain,
   1.404 +                                                            !aContainer->GetTransform().CanDraw2D());
   1.405 +
   1.406 +    effectChain.mPrimaryEffect = new EffectRenderTarget(surface);
   1.407 +
   1.408 +    gfx::Rect rect(visibleRect.x, visibleRect.y, visibleRect.width, visibleRect.height);
   1.409 +    gfx::Rect clipRect(aClipRect.x, aClipRect.y, aClipRect.width, aClipRect.height);
   1.410 +    aManager->GetCompositor()->DrawQuad(rect, clipRect, effectChain, opacity,
   1.411 +                                        aContainer->GetEffectiveTransform());
   1.412 +  }
   1.413 +
   1.414 +  if (aContainer->GetFrameMetrics().IsScrollable()) {
   1.415 +    const FrameMetrics& frame = aContainer->GetFrameMetrics();
   1.416 +    LayerRect layerBounds = ParentLayerRect(frame.mCompositionBounds) * ParentLayerToLayerScale(1.0);
   1.417 +    gfx::Rect rect(layerBounds.x, layerBounds.y, layerBounds.width, layerBounds.height);
   1.418 +    gfx::Rect clipRect(aClipRect.x, aClipRect.y, aClipRect.width, aClipRect.height);
   1.419 +    aManager->GetCompositor()->DrawDiagnostics(DIAGNOSTIC_CONTAINER,
   1.420 +                                               rect, clipRect,
   1.421 +                                               aContainer->GetEffectiveTransform());
   1.422 +  }
   1.423 +}
   1.424 +
   1.425 +ContainerLayerComposite::ContainerLayerComposite(LayerManagerComposite *aManager)
   1.426 +  : ContainerLayer(aManager, nullptr)
   1.427 +  , LayerComposite(aManager)
   1.428 +{
   1.429 +  MOZ_COUNT_CTOR(ContainerLayerComposite);
   1.430 +  mImplData = static_cast<LayerComposite*>(this);
   1.431 +}
   1.432 +
   1.433 +ContainerLayerComposite::~ContainerLayerComposite()
   1.434 +{
   1.435 +  MOZ_COUNT_DTOR(ContainerLayerComposite);
   1.436 +
   1.437 +  // We don't Destroy() on destruction here because this destructor
   1.438 +  // can be called after remote content has crashed, and it may not be
   1.439 +  // safe to free the IPC resources of our children.  Those resources
   1.440 +  // are automatically cleaned up by IPDL-generated code.
   1.441 +  //
   1.442 +  // In the common case of normal shutdown, either
   1.443 +  // LayerManagerComposite::Destroy(), a parent
   1.444 +  // *ContainerLayerComposite::Destroy(), or Disconnect() will trigger
   1.445 +  // cleanup of our resources.
   1.446 +  while (mFirstChild) {
   1.447 +    RemoveChild(mFirstChild);
   1.448 +  }
   1.449 +}
   1.450 +
   1.451 +void
   1.452 +ContainerLayerComposite::Destroy()
   1.453 +{
   1.454 +  if (!mDestroyed) {
   1.455 +    while (mFirstChild) {
   1.456 +      static_cast<LayerComposite*>(GetFirstChild()->ImplData())->Destroy();
   1.457 +      RemoveChild(mFirstChild);
   1.458 +    }
   1.459 +    mDestroyed = true;
   1.460 +  }
   1.461 +}
   1.462 +
   1.463 +LayerComposite*
   1.464 +ContainerLayerComposite::GetFirstChildComposite()
   1.465 +{
   1.466 +  if (!mFirstChild) {
   1.467 +    return nullptr;
   1.468 +   }
   1.469 +  return static_cast<LayerComposite*>(mFirstChild->ImplData());
   1.470 +}
   1.471 +
   1.472 +void
   1.473 +ContainerLayerComposite::RenderLayer(const nsIntRect& aClipRect)
   1.474 +{
   1.475 +  ContainerRender(this, mCompositeManager, aClipRect);
   1.476 +}
   1.477 +
   1.478 +void
   1.479 +ContainerLayerComposite::CleanupResources()
   1.480 +{
   1.481 +  for (Layer* l = GetFirstChild(); l; l = l->GetNextSibling()) {
   1.482 +    LayerComposite* layerToCleanup = static_cast<LayerComposite*>(l->ImplData());
   1.483 +    layerToCleanup->CleanupResources();
   1.484 +  }
   1.485 +}
   1.486 +
   1.487 +RefLayerComposite::RefLayerComposite(LayerManagerComposite* aManager)
   1.488 +  : RefLayer(aManager, nullptr)
   1.489 +  , LayerComposite(aManager)
   1.490 +{
   1.491 +  mImplData = static_cast<LayerComposite*>(this);
   1.492 +}
   1.493 +
   1.494 +RefLayerComposite::~RefLayerComposite()
   1.495 +{
   1.496 +  Destroy();
   1.497 +}
   1.498 +
   1.499 +void
   1.500 +RefLayerComposite::Destroy()
   1.501 +{
   1.502 +  MOZ_ASSERT(!mFirstChild);
   1.503 +  mDestroyed = true;
   1.504 +}
   1.505 +
   1.506 +LayerComposite*
   1.507 +RefLayerComposite::GetFirstChildComposite()
   1.508 +{
   1.509 +  if (!mFirstChild) {
   1.510 +    return nullptr;
   1.511 +   }
   1.512 +  return static_cast<LayerComposite*>(mFirstChild->ImplData());
   1.513 +}
   1.514 +
   1.515 +void
   1.516 +RefLayerComposite::RenderLayer(const nsIntRect& aClipRect)
   1.517 +{
   1.518 +  ContainerRender(this, mCompositeManager, aClipRect);
   1.519 +}
   1.520 +
   1.521 +void
   1.522 +RefLayerComposite::CleanupResources()
   1.523 +{
   1.524 +}
   1.525 +
   1.526 +} /* layers */
   1.527 +} /* mozilla */

mercurial