gfx/layers/composite/LayerManagerComposite.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/layers/composite/LayerManagerComposite.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,927 @@
     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 "LayerManagerComposite.h"
    1.10 +#include <stddef.h>                     // for size_t
    1.11 +#include <stdint.h>                     // for uint16_t, uint32_t
    1.12 +#include "CanvasLayerComposite.h"       // for CanvasLayerComposite
    1.13 +#include "ColorLayerComposite.h"        // for ColorLayerComposite
    1.14 +#include "Composer2D.h"                 // for Composer2D
    1.15 +#include "CompositableHost.h"           // for CompositableHost
    1.16 +#include "ContainerLayerComposite.h"    // for ContainerLayerComposite, etc
    1.17 +#include "FPSCounter.h"                 // for FPSState, FPSCounter
    1.18 +#include "FrameMetrics.h"               // for FrameMetrics
    1.19 +#include "GeckoProfiler.h"              // for profiler_set_frame_number, etc
    1.20 +#include "ImageLayerComposite.h"        // for ImageLayerComposite
    1.21 +#include "Layers.h"                     // for Layer, ContainerLayer, etc
    1.22 +#include "ThebesLayerComposite.h"       // for ThebesLayerComposite
    1.23 +#include "TiledLayerBuffer.h"           // for TiledLayerComposer
    1.24 +#include "Units.h"                      // for ScreenIntRect
    1.25 +#include "gfx2DGlue.h"                  // for ToMatrix4x4
    1.26 +#include "gfx3DMatrix.h"                // for gfx3DMatrix
    1.27 +#include "gfxPrefs.h"                   // for gfxPrefs
    1.28 +#ifdef XP_MACOSX
    1.29 +#include "gfxPlatformMac.h"
    1.30 +#endif
    1.31 +#include "gfxRect.h"                    // for gfxRect
    1.32 +#include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
    1.33 +#include "mozilla/RefPtr.h"             // for RefPtr, TemporaryRef
    1.34 +#include "mozilla/gfx/2D.h"             // for DrawTarget
    1.35 +#include "mozilla/gfx/Matrix.h"         // for Matrix4x4
    1.36 +#include "mozilla/gfx/Point.h"          // for IntSize, Point
    1.37 +#include "mozilla/gfx/Rect.h"           // for Rect
    1.38 +#include "mozilla/gfx/Types.h"          // for Color, SurfaceFormat
    1.39 +#include "mozilla/layers/Compositor.h"  // for Compositor
    1.40 +#include "mozilla/layers/CompositorTypes.h"
    1.41 +#include "mozilla/layers/Effects.h"     // for Effect, EffectChain, etc
    1.42 +#include "mozilla/layers/LayersTypes.h"  // for etc
    1.43 +#include "ipc/ShadowLayerUtils.h"
    1.44 +#include "mozilla/mozalloc.h"           // for operator new, etc
    1.45 +#include "nsAutoPtr.h"                  // for nsRefPtr
    1.46 +#include "nsCOMPtr.h"                   // for already_AddRefed
    1.47 +#include "nsDebug.h"                    // for NS_WARNING, NS_RUNTIMEABORT, etc
    1.48 +#include "nsISupportsImpl.h"            // for Layer::AddRef, etc
    1.49 +#include "nsIWidget.h"                  // for nsIWidget
    1.50 +#include "nsPoint.h"                    // for nsIntPoint
    1.51 +#include "nsRect.h"                     // for nsIntRect
    1.52 +#include "nsRegion.h"                   // for nsIntRegion, etc
    1.53 +#ifdef MOZ_WIDGET_ANDROID
    1.54 +#include <android/log.h>
    1.55 +#endif
    1.56 +#include "GeckoProfiler.h"
    1.57 +#include "TextRenderer.h"               // for TextRenderer
    1.58 +
    1.59 +class gfxContext;
    1.60 +struct nsIntSize;
    1.61 +
    1.62 +
    1.63 +namespace mozilla {
    1.64 +namespace layers {
    1.65 +
    1.66 +class ImageLayer;
    1.67 +
    1.68 +using namespace mozilla::gfx;
    1.69 +using namespace mozilla::gl;
    1.70 +
    1.71 +static LayerComposite*
    1.72 +ToLayerComposite(Layer* aLayer)
    1.73 +{
    1.74 +  return static_cast<LayerComposite*>(aLayer->ImplData());
    1.75 +}
    1.76 +
    1.77 +static void ClearSubtree(Layer* aLayer)
    1.78 +{
    1.79 +  ToLayerComposite(aLayer)->CleanupResources();
    1.80 +  for (Layer* child = aLayer->GetFirstChild(); child;
    1.81 +       child = child->GetNextSibling()) {
    1.82 +    ClearSubtree(child);
    1.83 +  }
    1.84 +}
    1.85 +
    1.86 +void
    1.87 +LayerManagerComposite::ClearCachedResources(Layer* aSubtree)
    1.88 +{
    1.89 +  MOZ_ASSERT(!aSubtree || aSubtree->Manager() == this);
    1.90 +  Layer* subtree = aSubtree ? aSubtree : mRoot.get();
    1.91 +  if (!subtree) {
    1.92 +    return;
    1.93 +  }
    1.94 +
    1.95 +  ClearSubtree(subtree);
    1.96 +  // FIXME [bjacob]
    1.97 +  // XXX the old LayerManagerOGL code had a mMaybeInvalidTree that it set to true here.
    1.98 +  // Do we need that?
    1.99 +}
   1.100 +
   1.101 +/**
   1.102 + * LayerManagerComposite
   1.103 + */
   1.104 +LayerManagerComposite::LayerManagerComposite(Compositor* aCompositor)
   1.105 +: mCompositor(aCompositor)
   1.106 +, mInTransaction(false)
   1.107 +, mIsCompositorReady(false)
   1.108 +, mDebugOverlayWantsNextFrame(false)
   1.109 +, mGeometryChanged(true)
   1.110 +{
   1.111 +  mTextRenderer = new TextRenderer(aCompositor);
   1.112 +  MOZ_ASSERT(aCompositor);
   1.113 +}
   1.114 +
   1.115 +LayerManagerComposite::~LayerManagerComposite()
   1.116 +{
   1.117 +  Destroy();
   1.118 +}
   1.119 +
   1.120 +
   1.121 +bool
   1.122 +LayerManagerComposite::Initialize()
   1.123 +{
   1.124 +  bool result = mCompositor->Initialize();
   1.125 +  return result;
   1.126 +}
   1.127 +
   1.128 +void
   1.129 +LayerManagerComposite::Destroy()
   1.130 +{
   1.131 +  if (!mDestroyed) {
   1.132 +    mCompositor->GetWidget()->CleanupWindowEffects();
   1.133 +    if (mRoot) {
   1.134 +      RootLayer()->Destroy();
   1.135 +    }
   1.136 +    mRoot = nullptr;
   1.137 +
   1.138 +    mCompositor->Destroy();
   1.139 +
   1.140 +    mDestroyed = true;
   1.141 +  }
   1.142 +}
   1.143 +
   1.144 +void
   1.145 +LayerManagerComposite::UpdateRenderBounds(const nsIntRect& aRect)
   1.146 +{
   1.147 +  mRenderBounds = aRect;
   1.148 +}
   1.149 +
   1.150 +void
   1.151 +LayerManagerComposite::BeginTransaction()
   1.152 +{
   1.153 +  mInTransaction = true;
   1.154 +  
   1.155 +  if (!mCompositor->Ready()) {
   1.156 +    return;
   1.157 +  }
   1.158 +  
   1.159 +  mIsCompositorReady = true;
   1.160 +
   1.161 +  if (Compositor::GetBackend() == LayersBackend::LAYERS_OPENGL ||
   1.162 +      Compositor::GetBackend() == LayersBackend::LAYERS_BASIC) {
   1.163 +    mClonedLayerTreeProperties = LayerProperties::CloneFrom(GetRoot());
   1.164 +  }
   1.165 +}
   1.166 +
   1.167 +void
   1.168 +LayerManagerComposite::BeginTransactionWithDrawTarget(DrawTarget* aTarget)
   1.169 +{
   1.170 +  mInTransaction = true;
   1.171 +  
   1.172 +  if (!mCompositor->Ready()) {
   1.173 +    return;
   1.174 +  }
   1.175 +
   1.176 +#ifdef MOZ_LAYERS_HAVE_LOG
   1.177 +  MOZ_LAYERS_LOG(("[----- BeginTransaction"));
   1.178 +  Log();
   1.179 +#endif
   1.180 +
   1.181 +  if (mDestroyed) {
   1.182 +    NS_WARNING("Call on destroyed layer manager");
   1.183 +    return;
   1.184 +  }
   1.185 +
   1.186 +  mIsCompositorReady = true;
   1.187 +  mCompositor->SetTargetContext(aTarget);
   1.188 +  mTarget = aTarget;
   1.189 +}
   1.190 +
   1.191 +bool
   1.192 +LayerManagerComposite::EndEmptyTransaction(EndTransactionFlags aFlags)
   1.193 +{
   1.194 +  NS_ASSERTION(mInTransaction, "Didn't call BeginTransaction?");
   1.195 +  if (!mRoot) {
   1.196 +    mInTransaction = false;
   1.197 +    mIsCompositorReady = false;
   1.198 +    return false;
   1.199 +  }
   1.200 +
   1.201 +  EndTransaction(nullptr, nullptr);
   1.202 +  return true;
   1.203 +}
   1.204 +
   1.205 +void
   1.206 +LayerManagerComposite::EndTransaction(DrawThebesLayerCallback aCallback,
   1.207 +                                      void* aCallbackData,
   1.208 +                                      EndTransactionFlags aFlags)
   1.209 +{
   1.210 +  NS_ASSERTION(mInTransaction, "Didn't call BeginTransaction?");
   1.211 +  NS_ASSERTION(!aCallback && !aCallbackData, "Not expecting callbacks here");
   1.212 +  mInTransaction = false;
   1.213 +
   1.214 +  if (!mIsCompositorReady) {
   1.215 +    return;
   1.216 +  }
   1.217 +  mIsCompositorReady = false;
   1.218 +
   1.219 +#ifdef MOZ_LAYERS_HAVE_LOG
   1.220 +  MOZ_LAYERS_LOG(("  ----- (beginning paint)"));
   1.221 +  Log();
   1.222 +#endif
   1.223 +
   1.224 +  if (mDestroyed) {
   1.225 +    NS_WARNING("Call on destroyed layer manager");
   1.226 +    return;
   1.227 +  }
   1.228 +
   1.229 +  if (mRoot && mClonedLayerTreeProperties) {
   1.230 +    nsIntRegion invalid =
   1.231 +      mClonedLayerTreeProperties->ComputeDifferences(mRoot, nullptr, &mGeometryChanged);
   1.232 +    mClonedLayerTreeProperties = nullptr;
   1.233 +
   1.234 +    mInvalidRegion.Or(mInvalidRegion, invalid);
   1.235 +  } else {
   1.236 +    mInvalidRegion.Or(mInvalidRegion, mRenderBounds);
   1.237 +  }
   1.238 +
   1.239 +  if (mRoot && !(aFlags & END_NO_IMMEDIATE_REDRAW)) {
   1.240 +    if (aFlags & END_NO_COMPOSITE) {
   1.241 +      // Apply pending tree updates before recomputing effective
   1.242 +      // properties.
   1.243 +      mRoot->ApplyPendingUpdatesToSubtree();
   1.244 +    }
   1.245 +
   1.246 +    // The results of our drawing always go directly into a pixel buffer,
   1.247 +    // so we don't need to pass any global transform here.
   1.248 +    mRoot->ComputeEffectiveTransforms(gfx::Matrix4x4());
   1.249 +
   1.250 +    Render();
   1.251 +    mGeometryChanged = false;
   1.252 +  }
   1.253 +
   1.254 +  mCompositor->SetTargetContext(nullptr);
   1.255 +  mTarget = nullptr;
   1.256 +
   1.257 +#ifdef MOZ_LAYERS_HAVE_LOG
   1.258 +  Log();
   1.259 +  MOZ_LAYERS_LOG(("]----- EndTransaction"));
   1.260 +#endif
   1.261 +}
   1.262 +
   1.263 +TemporaryRef<DrawTarget>
   1.264 +LayerManagerComposite::CreateOptimalMaskDrawTarget(const IntSize &aSize)
   1.265 +{
   1.266 +  NS_RUNTIMEABORT("Should only be called on the drawing side");
   1.267 +  return nullptr;
   1.268 +}
   1.269 +
   1.270 +already_AddRefed<ThebesLayer>
   1.271 +LayerManagerComposite::CreateThebesLayer()
   1.272 +{
   1.273 +  NS_RUNTIMEABORT("Should only be called on the drawing side");
   1.274 +  return nullptr;
   1.275 +}
   1.276 +
   1.277 +already_AddRefed<ContainerLayer>
   1.278 +LayerManagerComposite::CreateContainerLayer()
   1.279 +{
   1.280 +  NS_RUNTIMEABORT("Should only be called on the drawing side");
   1.281 +  return nullptr;
   1.282 +}
   1.283 +
   1.284 +already_AddRefed<ImageLayer>
   1.285 +LayerManagerComposite::CreateImageLayer()
   1.286 +{
   1.287 +  NS_RUNTIMEABORT("Should only be called on the drawing side");
   1.288 +  return nullptr;
   1.289 +}
   1.290 +
   1.291 +already_AddRefed<ColorLayer>
   1.292 +LayerManagerComposite::CreateColorLayer()
   1.293 +{
   1.294 +  NS_RUNTIMEABORT("Should only be called on the drawing side");
   1.295 +  return nullptr;
   1.296 +}
   1.297 +
   1.298 +already_AddRefed<CanvasLayer>
   1.299 +LayerManagerComposite::CreateCanvasLayer()
   1.300 +{
   1.301 +  NS_RUNTIMEABORT("Should only be called on the drawing side");
   1.302 +  return nullptr;
   1.303 +}
   1.304 +
   1.305 +LayerComposite*
   1.306 +LayerManagerComposite::RootLayer() const
   1.307 +{
   1.308 +  if (mDestroyed) {
   1.309 +    NS_WARNING("Call on destroyed layer manager");
   1.310 +    return nullptr;
   1.311 +  }
   1.312 +
   1.313 +  return ToLayerComposite(mRoot);
   1.314 +}
   1.315 +
   1.316 +// Size of the builtin font.
   1.317 +static const float FontHeight = 7.f;
   1.318 +static const float FontWidth = 4.f;
   1.319 +static const float FontStride = 4.f;
   1.320 +
   1.321 +// Scale the font when drawing it to the viewport for better readability.
   1.322 +static const float FontScaleX = 2.f;
   1.323 +static const float FontScaleY = 3.f;
   1.324 +
   1.325 +static void DrawDigits(unsigned int aValue,
   1.326 +		       int aOffsetX, int aOffsetY,
   1.327 +                       Compositor* aCompositor,
   1.328 +		       EffectChain& aEffectChain)
   1.329 +{
   1.330 +  if (aValue > 999) {
   1.331 +    aValue = 999;
   1.332 +  }
   1.333 +
   1.334 +  unsigned int divisor = 100;
   1.335 +  float textureWidth = FontWidth * 10;
   1.336 +  gfx::Float opacity = 1;
   1.337 +  gfx::Matrix4x4 transform;
   1.338 +  transform.Scale(FontScaleX, FontScaleY, 1);
   1.339 +
   1.340 +  for (size_t n = 0; n < 3; ++n) {
   1.341 +    unsigned int digit = aValue % (divisor * 10) / divisor;
   1.342 +    divisor /= 10;
   1.343 +
   1.344 +    RefPtr<TexturedEffect> texturedEffect = static_cast<TexturedEffect*>(aEffectChain.mPrimaryEffect.get());
   1.345 +    texturedEffect->mTextureCoords = Rect(float(digit * FontWidth) / textureWidth, 0, FontWidth / textureWidth, 1.0f);
   1.346 +
   1.347 +    Rect drawRect = Rect(aOffsetX + n * FontWidth, aOffsetY, FontWidth, FontHeight);
   1.348 +    Rect clipRect = Rect(0, 0, 300, 100);
   1.349 +    aCompositor->DrawQuad(drawRect, clipRect,
   1.350 +	aEffectChain, opacity, transform);
   1.351 +  }
   1.352 +}
   1.353 +
   1.354 +void FPSState::DrawFPS(TimeStamp aNow,
   1.355 +                       unsigned int aFillRatio,
   1.356 +                       Compositor* aCompositor)
   1.357 +{
   1.358 +  if (!mFPSTextureSource) {
   1.359 +    const char *text =
   1.360 +      "                                        "
   1.361 +      " XXX XX  XXX XXX X X XXX XXX XXX XXX XXX"
   1.362 +      " X X  X    X   X X X X   X     X X X X X"
   1.363 +      " X X  X  XXX XXX XXX XXX XXX   X XXX XXX"
   1.364 +      " X X  X  X     X   X   X X X   X X X   X"
   1.365 +      " XXX XXX XXX XXX   X XXX XXX   X XXX   X"
   1.366 +      "                                        ";
   1.367 +
   1.368 +    // Convert the text encoding above to RGBA.
   1.369 +    int w = FontWidth * 10;
   1.370 +    int h = FontHeight;
   1.371 +    uint32_t* buf = (uint32_t *) malloc(w * h * sizeof(uint32_t));
   1.372 +    for (int i = 0; i < h; i++) {
   1.373 +      for (int j = 0; j < w; j++) {
   1.374 +        uint32_t purple = 0xfff000ff;
   1.375 +        uint32_t white  = 0xffffffff;
   1.376 +        buf[i * w + j] = (text[i * w + j] == ' ') ? purple : white;
   1.377 +      }
   1.378 +    }
   1.379 +
   1.380 +   int bytesPerPixel = 4;
   1.381 +    RefPtr<DataSourceSurface> fpsSurface = Factory::CreateWrappingDataSourceSurface(
   1.382 +      reinterpret_cast<uint8_t*>(buf), w * bytesPerPixel, IntSize(w, h), SurfaceFormat::B8G8R8A8);
   1.383 +    mFPSTextureSource = aCompositor->CreateDataTextureSource();
   1.384 +    mFPSTextureSource->Update(fpsSurface);
   1.385 +  }
   1.386 +
   1.387 +  EffectChain effectChain;
   1.388 +  effectChain.mPrimaryEffect = CreateTexturedEffect(SurfaceFormat::B8G8R8A8, mFPSTextureSource, Filter::POINT);
   1.389 +
   1.390 +  unsigned int fps = unsigned(mCompositionFps.AddFrameAndGetFps(aNow));
   1.391 +  unsigned int txnFps = unsigned(mTransactionFps.GetFpsAt(aNow));
   1.392 +
   1.393 +  DrawDigits(fps, 0, 0, aCompositor, effectChain);
   1.394 +  DrawDigits(txnFps, FontWidth * 4, 0, aCompositor, effectChain);
   1.395 +  DrawDigits(aFillRatio, FontWidth * 8, 0, aCompositor, effectChain);
   1.396 +}
   1.397 +
   1.398 +static uint16_t sFrameCount = 0;
   1.399 +void
   1.400 +LayerManagerComposite::RenderDebugOverlay(const Rect& aBounds)
   1.401 +{
   1.402 +  if (gfxPrefs::LayersDrawFPS()) {
   1.403 +    if (!mFPS) {
   1.404 +      mFPS = new FPSState();
   1.405 +    }
   1.406 +
   1.407 +    float fillRatio = mCompositor->GetFillRatio();
   1.408 +    mFPS->DrawFPS(TimeStamp::Now(), unsigned(fillRatio), mCompositor);
   1.409 +  } else {
   1.410 +    mFPS = nullptr;
   1.411 +  }
   1.412 +
   1.413 +  if (gfxPrefs::DrawFrameCounter()) {
   1.414 +    profiler_set_frame_number(sFrameCount);
   1.415 +
   1.416 +    uint16_t frameNumber = sFrameCount;
   1.417 +    const uint16_t bitWidth = 3;
   1.418 +    float opacity = 1.0;
   1.419 +    gfx::Rect clip(0,0, bitWidth*16, bitWidth);
   1.420 +    for (size_t i = 0; i < 16; i++) {
   1.421 +
   1.422 +      gfx::Color bitColor;
   1.423 +      if ((frameNumber >> i) & 0x1) {
   1.424 +        bitColor = gfx::Color(0, 0, 0, 1.0);
   1.425 +      } else {
   1.426 +        bitColor = gfx::Color(1.0, 1.0, 1.0, 1.0);
   1.427 +      }
   1.428 +      EffectChain effects;
   1.429 +      effects.mPrimaryEffect = new EffectSolidColor(bitColor);
   1.430 +      mCompositor->DrawQuad(gfx::Rect(bitWidth*i, 0, bitWidth, bitWidth),
   1.431 +                            clip,
   1.432 +                            effects,
   1.433 +                            opacity,
   1.434 +                            gfx::Matrix4x4());
   1.435 +    }
   1.436 +    // We intentionally overflow at 2^16.
   1.437 +    sFrameCount++;
   1.438 +  }
   1.439 +}
   1.440 +
   1.441 +void
   1.442 +LayerManagerComposite::Render()
   1.443 +{
   1.444 +  PROFILER_LABEL("LayerManagerComposite", "Render");
   1.445 +  if (mDestroyed) {
   1.446 +    NS_WARNING("Call on destroyed layer manager");
   1.447 +    return;
   1.448 +  }
   1.449 +
   1.450 +  if (gfxPrefs::LayersDump()) {
   1.451 +    this->Dump();
   1.452 +  }
   1.453 +
   1.454 +  /** Our more efficient but less powerful alter ego, if one is available. */
   1.455 +  nsRefPtr<Composer2D> composer2D = mCompositor->GetWidget()->GetComposer2D();
   1.456 +
   1.457 +  if (!mTarget && composer2D && composer2D->TryRender(mRoot, mWorldMatrix, mGeometryChanged)) {
   1.458 +    if (mFPS) {
   1.459 +      double fps = mFPS->mCompositionFps.AddFrameAndGetFps(TimeStamp::Now());
   1.460 +      if (gfxPrefs::LayersDrawFPS()) {
   1.461 +        printf_stderr("HWComposer: FPS is %g\n", fps);
   1.462 +      }
   1.463 +    }
   1.464 +    mCompositor->EndFrameForExternalComposition(mWorldMatrix);
   1.465 +    return;
   1.466 +  }
   1.467 +
   1.468 +  {
   1.469 +    PROFILER_LABEL("LayerManagerComposite", "PreRender");
   1.470 +    if (!mCompositor->GetWidget()->PreRender(this)) {
   1.471 +      return;
   1.472 +    }
   1.473 +  }
   1.474 +
   1.475 +  nsIntRect clipRect;
   1.476 +  Rect bounds(mRenderBounds.x, mRenderBounds.y, mRenderBounds.width, mRenderBounds.height);
   1.477 +  Rect actualBounds;
   1.478 +  if (mRoot->GetClipRect()) {
   1.479 +    clipRect = *mRoot->GetClipRect();
   1.480 +    WorldTransformRect(clipRect);
   1.481 +    Rect rect(clipRect.x, clipRect.y, clipRect.width, clipRect.height);
   1.482 +    mCompositor->BeginFrame(mInvalidRegion, &rect, mWorldMatrix, bounds, nullptr, &actualBounds);
   1.483 +  } else {
   1.484 +    gfx::Rect rect;
   1.485 +    mCompositor->BeginFrame(mInvalidRegion, nullptr, mWorldMatrix, bounds, &rect, &actualBounds);
   1.486 +    clipRect = nsIntRect(rect.x, rect.y, rect.width, rect.height);
   1.487 +  }
   1.488 +
   1.489 +  // Reset the invalid region now that we've begun compositing.
   1.490 +  mInvalidRegion.SetEmpty();
   1.491 +
   1.492 +  if (actualBounds.IsEmpty()) {
   1.493 +    mCompositor->GetWidget()->PostRender(this);
   1.494 +    return;
   1.495 +  }
   1.496 +
   1.497 +  // Allow widget to render a custom background.
   1.498 +  mCompositor->GetWidget()->DrawWindowUnderlay(this, nsIntRect(actualBounds.x,
   1.499 +                                                               actualBounds.y,
   1.500 +                                                               actualBounds.width,
   1.501 +                                                               actualBounds.height));
   1.502 +
   1.503 +  // Render our layers.
   1.504 +  RootLayer()->RenderLayer(clipRect);
   1.505 +
   1.506 +  if (!mRegionToClear.IsEmpty()) {
   1.507 +    nsIntRegionRectIterator iter(mRegionToClear);
   1.508 +    const nsIntRect *r;
   1.509 +    while ((r = iter.Next())) {
   1.510 +      mCompositor->ClearRect(Rect(r->x, r->y, r->width, r->height));
   1.511 +    }
   1.512 +  }
   1.513 +
   1.514 +  // Allow widget to render a custom foreground.
   1.515 +  mCompositor->GetWidget()->DrawWindowOverlay(this, nsIntRect(actualBounds.x,
   1.516 +                                                              actualBounds.y,
   1.517 +                                                              actualBounds.width,
   1.518 +                                                              actualBounds.height));
   1.519 +
   1.520 +  // Debugging
   1.521 +  RenderDebugOverlay(actualBounds);
   1.522 +
   1.523 +  {
   1.524 +    PROFILER_LABEL("LayerManagerComposite", "EndFrame");
   1.525 +    mCompositor->EndFrame();
   1.526 +    mCompositor->SetFBAcquireFence(mRoot);
   1.527 +  }
   1.528 +
   1.529 +  mCompositor->GetWidget()->PostRender(this);
   1.530 +
   1.531 +  RecordFrame();
   1.532 +}
   1.533 +
   1.534 +void
   1.535 +LayerManagerComposite::SetWorldTransform(const gfx::Matrix& aMatrix)
   1.536 +{
   1.537 +  NS_ASSERTION(aMatrix.PreservesAxisAlignedRectangles(),
   1.538 +               "SetWorldTransform only accepts matrices that satisfy PreservesAxisAlignedRectangles");
   1.539 +  NS_ASSERTION(!aMatrix.HasNonIntegerScale(),
   1.540 +               "SetWorldTransform only accepts matrices with integer scale");
   1.541 +
   1.542 +  mWorldMatrix = aMatrix;
   1.543 +}
   1.544 +
   1.545 +gfx::Matrix&
   1.546 +LayerManagerComposite::GetWorldTransform(void)
   1.547 +{
   1.548 +  return mWorldMatrix;
   1.549 +}
   1.550 +
   1.551 +void
   1.552 +LayerManagerComposite::WorldTransformRect(nsIntRect& aRect)
   1.553 +{
   1.554 +  gfx::Rect grect(aRect.x, aRect.y, aRect.width, aRect.height);
   1.555 +  grect = mWorldMatrix.TransformBounds(grect);
   1.556 +  aRect.SetRect(grect.X(), grect.Y(), grect.Width(), grect.Height());
   1.557 +}
   1.558 +
   1.559 +static void
   1.560 +SubtractTransformedRegion(nsIntRegion& aRegion,
   1.561 +                          const nsIntRegion& aRegionToSubtract,
   1.562 +                          const gfx3DMatrix& aTransform)
   1.563 +{
   1.564 +  if (aRegionToSubtract.IsEmpty()) {
   1.565 +    return;
   1.566 +  }
   1.567 +
   1.568 +  // For each rect in the region, find out its bounds in screen space and
   1.569 +  // subtract it from the screen region.
   1.570 +  nsIntRegionRectIterator it(aRegionToSubtract);
   1.571 +  while (const nsIntRect* rect = it.Next()) {
   1.572 +    gfxRect incompleteRect = aTransform.TransformBounds(gfxRect(*rect));
   1.573 +    aRegion.Sub(aRegion, nsIntRect(incompleteRect.x,
   1.574 +                                   incompleteRect.y,
   1.575 +                                   incompleteRect.width,
   1.576 +                                   incompleteRect.height));
   1.577 +  }
   1.578 +}
   1.579 +
   1.580 +/* static */ void
   1.581 +LayerManagerComposite::ComputeRenderIntegrityInternal(Layer* aLayer,
   1.582 +                                                      nsIntRegion& aScreenRegion,
   1.583 +                                                      nsIntRegion& aLowPrecisionScreenRegion,
   1.584 +                                                      const gfx3DMatrix& aTransform)
   1.585 +{
   1.586 +  if (aLayer->GetOpacity() <= 0.f ||
   1.587 +      (aScreenRegion.IsEmpty() && aLowPrecisionScreenRegion.IsEmpty())) {
   1.588 +    return;
   1.589 +  }
   1.590 +
   1.591 +  // If the layer's a container, recurse into all of its children
   1.592 +  ContainerLayer* container = aLayer->AsContainerLayer();
   1.593 +  if (container) {
   1.594 +    // Accumulate the transform of intermediate surfaces
   1.595 +    gfx3DMatrix transform = aTransform;
   1.596 +    if (container->UseIntermediateSurface()) {
   1.597 +      gfx::To3DMatrix(aLayer->GetEffectiveTransform(), transform);
   1.598 +      transform.PreMultiply(aTransform);
   1.599 +    }
   1.600 +    for (Layer* child = aLayer->GetFirstChild(); child;
   1.601 +         child = child->GetNextSibling()) {
   1.602 +      ComputeRenderIntegrityInternal(child, aScreenRegion, aLowPrecisionScreenRegion, transform);
   1.603 +    }
   1.604 +    return;
   1.605 +  }
   1.606 +
   1.607 +  // Only thebes layers can be incomplete
   1.608 +  ThebesLayer* thebesLayer = aLayer->AsThebesLayer();
   1.609 +  if (!thebesLayer) {
   1.610 +    return;
   1.611 +  }
   1.612 +
   1.613 +  // See if there's any incomplete rendering
   1.614 +  nsIntRegion incompleteRegion = aLayer->GetEffectiveVisibleRegion();
   1.615 +  incompleteRegion.Sub(incompleteRegion, thebesLayer->GetValidRegion());
   1.616 +
   1.617 +  if (!incompleteRegion.IsEmpty()) {
   1.618 +    // Calculate the transform to get between screen and layer space
   1.619 +    gfx3DMatrix transformToScreen;
   1.620 +    To3DMatrix(aLayer->GetEffectiveTransform(), transformToScreen);
   1.621 +    transformToScreen.PreMultiply(aTransform);
   1.622 +
   1.623 +    SubtractTransformedRegion(aScreenRegion, incompleteRegion, transformToScreen);
   1.624 +
   1.625 +    // See if there's any incomplete low-precision rendering
   1.626 +    TiledLayerComposer* composer = nullptr;
   1.627 +    LayerComposite* shadow = aLayer->AsLayerComposite();
   1.628 +    if (shadow) {
   1.629 +      composer = shadow->GetTiledLayerComposer();
   1.630 +      if (composer) {
   1.631 +        incompleteRegion.Sub(incompleteRegion, composer->GetValidLowPrecisionRegion());
   1.632 +        if (!incompleteRegion.IsEmpty()) {
   1.633 +          SubtractTransformedRegion(aLowPrecisionScreenRegion, incompleteRegion, transformToScreen);
   1.634 +        }
   1.635 +      }
   1.636 +    }
   1.637 +
   1.638 +    // If we can't get a valid low precision region, assume it's the same as
   1.639 +    // the high precision region.
   1.640 +    if (!composer) {
   1.641 +      SubtractTransformedRegion(aLowPrecisionScreenRegion, incompleteRegion, transformToScreen);
   1.642 +    }
   1.643 +  }
   1.644 +}
   1.645 +
   1.646 +#ifdef MOZ_ANDROID_OMTC
   1.647 +static float
   1.648 +GetDisplayportCoverage(const CSSRect& aDisplayPort,
   1.649 +                       const gfx3DMatrix& aTransformToScreen,
   1.650 +                       const nsIntRect& aScreenRect)
   1.651 +{
   1.652 +  gfxRect transformedDisplayport =
   1.653 +    aTransformToScreen.TransformBounds(gfxRect(aDisplayPort.x,
   1.654 +                                               aDisplayPort.y,
   1.655 +                                               aDisplayPort.width,
   1.656 +                                               aDisplayPort.height));
   1.657 +  transformedDisplayport.RoundOut();
   1.658 +  nsIntRect displayport = nsIntRect(transformedDisplayport.x,
   1.659 +                                    transformedDisplayport.y,
   1.660 +                                    transformedDisplayport.width,
   1.661 +                                    transformedDisplayport.height);
   1.662 +  if (!displayport.Contains(aScreenRect)) {
   1.663 +    nsIntRegion coveredRegion;
   1.664 +    coveredRegion.And(aScreenRect, displayport);
   1.665 +    return coveredRegion.Area() / (float)(aScreenRect.width * aScreenRect.height);
   1.666 +  }
   1.667 +
   1.668 +  return 1.0f;
   1.669 +}
   1.670 +#endif // MOZ_ANDROID_OMTC
   1.671 +
   1.672 +float
   1.673 +LayerManagerComposite::ComputeRenderIntegrity()
   1.674 +{
   1.675 +  // We only ever have incomplete rendering when progressive tiles are enabled.
   1.676 +  Layer* root = GetRoot();
   1.677 +  if (!gfxPrefs::UseProgressiveTilePainting() || !root) {
   1.678 +    return 1.f;
   1.679 +  }
   1.680 +
   1.681 +  const FrameMetrics& rootMetrics = root->AsContainerLayer()->GetFrameMetrics();
   1.682 +  nsIntRect screenRect(rootMetrics.mCompositionBounds.x,
   1.683 +                       rootMetrics.mCompositionBounds.y,
   1.684 +                       rootMetrics.mCompositionBounds.width,
   1.685 +                       rootMetrics.mCompositionBounds.height);
   1.686 +
   1.687 +  float lowPrecisionMultiplier = 1.0f;
   1.688 +  float highPrecisionMultiplier = 1.0f;
   1.689 +
   1.690 +#ifdef MOZ_ANDROID_OMTC
   1.691 +  // Use the transform on the primary scrollable layer and its FrameMetrics
   1.692 +  // to find out how much of the viewport the current displayport covers
   1.693 +  Layer* primaryScrollable = GetPrimaryScrollableLayer();
   1.694 +  if (primaryScrollable) {
   1.695 +    // This is derived from the code in
   1.696 +    // AsyncCompositionManager::TransformScrollableLayer
   1.697 +    const FrameMetrics& metrics = primaryScrollable->AsContainerLayer()->GetFrameMetrics();
   1.698 +    gfx3DMatrix transform;
   1.699 +    gfx::To3DMatrix(primaryScrollable->GetEffectiveTransform(), transform);
   1.700 +    transform.ScalePost(metrics.mResolution.scale, metrics.mResolution.scale, 1);
   1.701 +
   1.702 +    // Clip the screen rect to the document bounds
   1.703 +    gfxRect documentBounds =
   1.704 +      transform.TransformBounds(gfxRect(metrics.mScrollableRect.x - metrics.GetScrollOffset().x,
   1.705 +                                        metrics.mScrollableRect.y - metrics.GetScrollOffset().y,
   1.706 +                                        metrics.mScrollableRect.width,
   1.707 +                                        metrics.mScrollableRect.height));
   1.708 +    documentBounds.RoundOut();
   1.709 +    screenRect = screenRect.Intersect(nsIntRect(documentBounds.x, documentBounds.y,
   1.710 +                                                documentBounds.width, documentBounds.height));
   1.711 +
   1.712 +    // If the screen rect is empty, the user has scrolled entirely into
   1.713 +    // over-scroll and so we can be considered to have full integrity.
   1.714 +    if (screenRect.IsEmpty()) {
   1.715 +      return 1.0f;
   1.716 +    }
   1.717 +
   1.718 +    // Work out how much of the critical display-port covers the screen
   1.719 +    bool hasLowPrecision = false;
   1.720 +    if (!metrics.mCriticalDisplayPort.IsEmpty()) {
   1.721 +      hasLowPrecision = true;
   1.722 +      highPrecisionMultiplier =
   1.723 +        GetDisplayportCoverage(metrics.mCriticalDisplayPort, transform, screenRect);
   1.724 +    }
   1.725 +
   1.726 +    // Work out how much of the display-port covers the screen
   1.727 +    if (!metrics.mDisplayPort.IsEmpty()) {
   1.728 +      if (hasLowPrecision) {
   1.729 +        lowPrecisionMultiplier =
   1.730 +          GetDisplayportCoverage(metrics.mDisplayPort, transform, screenRect);
   1.731 +      } else {
   1.732 +        lowPrecisionMultiplier = highPrecisionMultiplier =
   1.733 +          GetDisplayportCoverage(metrics.mDisplayPort, transform, screenRect);
   1.734 +      }
   1.735 +    }
   1.736 +  }
   1.737 +
   1.738 +  // If none of the screen is covered, we have zero integrity.
   1.739 +  if (highPrecisionMultiplier <= 0.0f && lowPrecisionMultiplier <= 0.0f) {
   1.740 +    return 0.0f;
   1.741 +  }
   1.742 +#endif // MOZ_ANDROID_OMTC
   1.743 +
   1.744 +  nsIntRegion screenRegion(screenRect);
   1.745 +  nsIntRegion lowPrecisionScreenRegion(screenRect);
   1.746 +  gfx3DMatrix transform;
   1.747 +  ComputeRenderIntegrityInternal(root, screenRegion,
   1.748 +                                 lowPrecisionScreenRegion, transform);
   1.749 +
   1.750 +  if (!screenRegion.IsEqual(screenRect)) {
   1.751 +    // Calculate the area of the region. All rects in an nsRegion are
   1.752 +    // non-overlapping.
   1.753 +    float screenArea = screenRect.width * screenRect.height;
   1.754 +    float highPrecisionIntegrity = screenRegion.Area() / screenArea;
   1.755 +    float lowPrecisionIntegrity = 1.f;
   1.756 +    if (!lowPrecisionScreenRegion.IsEqual(screenRect)) {
   1.757 +      lowPrecisionIntegrity = lowPrecisionScreenRegion.Area() / screenArea;
   1.758 +    }
   1.759 +
   1.760 +    return ((highPrecisionIntegrity * highPrecisionMultiplier) +
   1.761 +            (lowPrecisionIntegrity * lowPrecisionMultiplier)) / 2;
   1.762 +  }
   1.763 +
   1.764 +  return 1.f;
   1.765 +}
   1.766 +
   1.767 +already_AddRefed<ThebesLayerComposite>
   1.768 +LayerManagerComposite::CreateThebesLayerComposite()
   1.769 +{
   1.770 +  if (mDestroyed) {
   1.771 +    NS_WARNING("Call on destroyed layer manager");
   1.772 +    return nullptr;
   1.773 +  }
   1.774 +  return nsRefPtr<ThebesLayerComposite>(new ThebesLayerComposite(this)).forget();
   1.775 +}
   1.776 +
   1.777 +already_AddRefed<ContainerLayerComposite>
   1.778 +LayerManagerComposite::CreateContainerLayerComposite()
   1.779 +{
   1.780 +  if (mDestroyed) {
   1.781 +    NS_WARNING("Call on destroyed layer manager");
   1.782 +    return nullptr;
   1.783 +  }
   1.784 +  return nsRefPtr<ContainerLayerComposite>(new ContainerLayerComposite(this)).forget();
   1.785 +}
   1.786 +
   1.787 +already_AddRefed<ImageLayerComposite>
   1.788 +LayerManagerComposite::CreateImageLayerComposite()
   1.789 +{
   1.790 +  if (mDestroyed) {
   1.791 +    NS_WARNING("Call on destroyed layer manager");
   1.792 +    return nullptr;
   1.793 +  }
   1.794 +  return nsRefPtr<ImageLayerComposite>(new ImageLayerComposite(this)).forget();
   1.795 +}
   1.796 +
   1.797 +already_AddRefed<ColorLayerComposite>
   1.798 +LayerManagerComposite::CreateColorLayerComposite()
   1.799 +{
   1.800 +  if (LayerManagerComposite::mDestroyed) {
   1.801 +    NS_WARNING("Call on destroyed layer manager");
   1.802 +    return nullptr;
   1.803 +  }
   1.804 +  return nsRefPtr<ColorLayerComposite>(new ColorLayerComposite(this)).forget();
   1.805 +}
   1.806 +
   1.807 +already_AddRefed<CanvasLayerComposite>
   1.808 +LayerManagerComposite::CreateCanvasLayerComposite()
   1.809 +{
   1.810 +  if (LayerManagerComposite::mDestroyed) {
   1.811 +    NS_WARNING("Call on destroyed layer manager");
   1.812 +    return nullptr;
   1.813 +  }
   1.814 +  return nsRefPtr<CanvasLayerComposite>(new CanvasLayerComposite(this)).forget();
   1.815 +}
   1.816 +
   1.817 +already_AddRefed<RefLayerComposite>
   1.818 +LayerManagerComposite::CreateRefLayerComposite()
   1.819 +{
   1.820 +  if (LayerManagerComposite::mDestroyed) {
   1.821 +    NS_WARNING("Call on destroyed layer manager");
   1.822 +    return nullptr;
   1.823 +  }
   1.824 +  return nsRefPtr<RefLayerComposite>(new RefLayerComposite(this)).forget();
   1.825 +}
   1.826 +
   1.827 +LayerManagerComposite::AutoAddMaskEffect::AutoAddMaskEffect(Layer* aMaskLayer,
   1.828 +                                                            EffectChain& aEffects,
   1.829 +                                                            bool aIs3D)
   1.830 +  : mCompositable(nullptr)
   1.831 +{
   1.832 +  if (!aMaskLayer) {
   1.833 +    return;
   1.834 +  }
   1.835 +
   1.836 +  mCompositable = ToLayerComposite(aMaskLayer)->GetCompositableHost();
   1.837 +  if (!mCompositable) {
   1.838 +    NS_WARNING("Mask layer with no compositable host");
   1.839 +    return;
   1.840 +  }
   1.841 +
   1.842 +  if (!mCompositable->AddMaskEffect(aEffects, aMaskLayer->GetEffectiveTransform(), aIs3D)) {
   1.843 +    mCompositable = nullptr;
   1.844 +  }
   1.845 +}
   1.846 +
   1.847 +LayerManagerComposite::AutoAddMaskEffect::~AutoAddMaskEffect()
   1.848 +{
   1.849 +  if (!mCompositable) {
   1.850 +    return;
   1.851 +  }
   1.852 +
   1.853 +  mCompositable->RemoveMaskEffect();
   1.854 +}
   1.855 +
   1.856 +TemporaryRef<DrawTarget>
   1.857 +LayerManagerComposite::CreateDrawTarget(const IntSize &aSize,
   1.858 +                                        SurfaceFormat aFormat)
   1.859 +{
   1.860 +#ifdef XP_MACOSX
   1.861 +  // We don't want to accelerate if the surface is too small which indicates
   1.862 +  // that it's likely used for an icon/static image. We also don't want to
   1.863 +  // accelerate anything that is above the maximum texture size of weakest gpu.
   1.864 +  // Safari uses 5000 area as the minimum for acceleration, we decided 64^2 is more logical.
   1.865 +  bool useAcceleration = aSize.width <= 4096 && aSize.height <= 4096 &&
   1.866 +                         aSize.width > 64 && aSize.height > 64 &&
   1.867 +                         gfxPlatformMac::GetPlatform()->UseAcceleratedCanvas();
   1.868 +  if (useAcceleration) {
   1.869 +    return Factory::CreateDrawTarget(BackendType::COREGRAPHICS_ACCELERATED,
   1.870 +                                     aSize, aFormat);
   1.871 +  }
   1.872 +#endif
   1.873 +  return LayerManager::CreateDrawTarget(aSize, aFormat);
   1.874 +}
   1.875 +
   1.876 +LayerComposite::LayerComposite(LayerManagerComposite *aManager)
   1.877 +  : mCompositeManager(aManager)
   1.878 +  , mCompositor(aManager->GetCompositor())
   1.879 +  , mShadowOpacity(1.0)
   1.880 +  , mUseShadowClipRect(false)
   1.881 +  , mShadowTransformSetByAnimation(false)
   1.882 +  , mDestroyed(false)
   1.883 +  , mLayerComposited(false)
   1.884 +{ }
   1.885 +
   1.886 +LayerComposite::~LayerComposite()
   1.887 +{
   1.888 +}
   1.889 +
   1.890 +void
   1.891 +LayerComposite::Destroy()
   1.892 +{
   1.893 +  if (!mDestroyed) {
   1.894 +    mDestroyed = true;
   1.895 +    CleanupResources();
   1.896 +  }
   1.897 +}
   1.898 +
   1.899 +bool
   1.900 +LayerManagerComposite::CanUseCanvasLayerForSize(const IntSize &aSize)
   1.901 +{
   1.902 +  return mCompositor->CanUseCanvasLayerForSize(gfx::IntSize(aSize.width,
   1.903 +                                                            aSize.height));
   1.904 +}
   1.905 +
   1.906 +void
   1.907 +LayerManagerComposite::NotifyShadowTreeTransaction()
   1.908 +{
   1.909 +  if (mFPS) {
   1.910 +    mFPS->NotifyShadowTreeTransaction();
   1.911 +  }
   1.912 +}
   1.913 +
   1.914 +#ifndef MOZ_HAVE_PLATFORM_SPECIFIC_LAYER_BUFFERS
   1.915 +
   1.916 +/*static*/ bool
   1.917 +LayerManagerComposite::SupportsDirectTexturing()
   1.918 +{
   1.919 +  return false;
   1.920 +}
   1.921 +
   1.922 +/*static*/ void
   1.923 +LayerManagerComposite::PlatformSyncBeforeReplyUpdate()
   1.924 +{
   1.925 +}
   1.926 +
   1.927 +#endif  // !defined(MOZ_HAVE_PLATFORM_SPECIFIC_LAYER_BUFFERS)
   1.928 +
   1.929 +} /* layers */
   1.930 +} /* mozilla */

mercurial