gfx/layers/composite/LayerManagerComposite.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "LayerManagerComposite.h"
     7 #include <stddef.h>                     // for size_t
     8 #include <stdint.h>                     // for uint16_t, uint32_t
     9 #include "CanvasLayerComposite.h"       // for CanvasLayerComposite
    10 #include "ColorLayerComposite.h"        // for ColorLayerComposite
    11 #include "Composer2D.h"                 // for Composer2D
    12 #include "CompositableHost.h"           // for CompositableHost
    13 #include "ContainerLayerComposite.h"    // for ContainerLayerComposite, etc
    14 #include "FPSCounter.h"                 // for FPSState, FPSCounter
    15 #include "FrameMetrics.h"               // for FrameMetrics
    16 #include "GeckoProfiler.h"              // for profiler_set_frame_number, etc
    17 #include "ImageLayerComposite.h"        // for ImageLayerComposite
    18 #include "Layers.h"                     // for Layer, ContainerLayer, etc
    19 #include "ThebesLayerComposite.h"       // for ThebesLayerComposite
    20 #include "TiledLayerBuffer.h"           // for TiledLayerComposer
    21 #include "Units.h"                      // for ScreenIntRect
    22 #include "gfx2DGlue.h"                  // for ToMatrix4x4
    23 #include "gfx3DMatrix.h"                // for gfx3DMatrix
    24 #include "gfxPrefs.h"                   // for gfxPrefs
    25 #ifdef XP_MACOSX
    26 #include "gfxPlatformMac.h"
    27 #endif
    28 #include "gfxRect.h"                    // for gfxRect
    29 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
    30 #include "mozilla/RefPtr.h"             // for RefPtr, TemporaryRef
    31 #include "mozilla/gfx/2D.h"             // for DrawTarget
    32 #include "mozilla/gfx/Matrix.h"         // for Matrix4x4
    33 #include "mozilla/gfx/Point.h"          // for IntSize, Point
    34 #include "mozilla/gfx/Rect.h"           // for Rect
    35 #include "mozilla/gfx/Types.h"          // for Color, SurfaceFormat
    36 #include "mozilla/layers/Compositor.h"  // for Compositor
    37 #include "mozilla/layers/CompositorTypes.h"
    38 #include "mozilla/layers/Effects.h"     // for Effect, EffectChain, etc
    39 #include "mozilla/layers/LayersTypes.h"  // for etc
    40 #include "ipc/ShadowLayerUtils.h"
    41 #include "mozilla/mozalloc.h"           // for operator new, etc
    42 #include "nsAutoPtr.h"                  // for nsRefPtr
    43 #include "nsCOMPtr.h"                   // for already_AddRefed
    44 #include "nsDebug.h"                    // for NS_WARNING, NS_RUNTIMEABORT, etc
    45 #include "nsISupportsImpl.h"            // for Layer::AddRef, etc
    46 #include "nsIWidget.h"                  // for nsIWidget
    47 #include "nsPoint.h"                    // for nsIntPoint
    48 #include "nsRect.h"                     // for nsIntRect
    49 #include "nsRegion.h"                   // for nsIntRegion, etc
    50 #ifdef MOZ_WIDGET_ANDROID
    51 #include <android/log.h>
    52 #endif
    53 #include "GeckoProfiler.h"
    54 #include "TextRenderer.h"               // for TextRenderer
    56 class gfxContext;
    57 struct nsIntSize;
    60 namespace mozilla {
    61 namespace layers {
    63 class ImageLayer;
    65 using namespace mozilla::gfx;
    66 using namespace mozilla::gl;
    68 static LayerComposite*
    69 ToLayerComposite(Layer* aLayer)
    70 {
    71   return static_cast<LayerComposite*>(aLayer->ImplData());
    72 }
    74 static void ClearSubtree(Layer* aLayer)
    75 {
    76   ToLayerComposite(aLayer)->CleanupResources();
    77   for (Layer* child = aLayer->GetFirstChild(); child;
    78        child = child->GetNextSibling()) {
    79     ClearSubtree(child);
    80   }
    81 }
    83 void
    84 LayerManagerComposite::ClearCachedResources(Layer* aSubtree)
    85 {
    86   MOZ_ASSERT(!aSubtree || aSubtree->Manager() == this);
    87   Layer* subtree = aSubtree ? aSubtree : mRoot.get();
    88   if (!subtree) {
    89     return;
    90   }
    92   ClearSubtree(subtree);
    93   // FIXME [bjacob]
    94   // XXX the old LayerManagerOGL code had a mMaybeInvalidTree that it set to true here.
    95   // Do we need that?
    96 }
    98 /**
    99  * LayerManagerComposite
   100  */
   101 LayerManagerComposite::LayerManagerComposite(Compositor* aCompositor)
   102 : mCompositor(aCompositor)
   103 , mInTransaction(false)
   104 , mIsCompositorReady(false)
   105 , mDebugOverlayWantsNextFrame(false)
   106 , mGeometryChanged(true)
   107 {
   108   mTextRenderer = new TextRenderer(aCompositor);
   109   MOZ_ASSERT(aCompositor);
   110 }
   112 LayerManagerComposite::~LayerManagerComposite()
   113 {
   114   Destroy();
   115 }
   118 bool
   119 LayerManagerComposite::Initialize()
   120 {
   121   bool result = mCompositor->Initialize();
   122   return result;
   123 }
   125 void
   126 LayerManagerComposite::Destroy()
   127 {
   128   if (!mDestroyed) {
   129     mCompositor->GetWidget()->CleanupWindowEffects();
   130     if (mRoot) {
   131       RootLayer()->Destroy();
   132     }
   133     mRoot = nullptr;
   135     mCompositor->Destroy();
   137     mDestroyed = true;
   138   }
   139 }
   141 void
   142 LayerManagerComposite::UpdateRenderBounds(const nsIntRect& aRect)
   143 {
   144   mRenderBounds = aRect;
   145 }
   147 void
   148 LayerManagerComposite::BeginTransaction()
   149 {
   150   mInTransaction = true;
   152   if (!mCompositor->Ready()) {
   153     return;
   154   }
   156   mIsCompositorReady = true;
   158   if (Compositor::GetBackend() == LayersBackend::LAYERS_OPENGL ||
   159       Compositor::GetBackend() == LayersBackend::LAYERS_BASIC) {
   160     mClonedLayerTreeProperties = LayerProperties::CloneFrom(GetRoot());
   161   }
   162 }
   164 void
   165 LayerManagerComposite::BeginTransactionWithDrawTarget(DrawTarget* aTarget)
   166 {
   167   mInTransaction = true;
   169   if (!mCompositor->Ready()) {
   170     return;
   171   }
   173 #ifdef MOZ_LAYERS_HAVE_LOG
   174   MOZ_LAYERS_LOG(("[----- BeginTransaction"));
   175   Log();
   176 #endif
   178   if (mDestroyed) {
   179     NS_WARNING("Call on destroyed layer manager");
   180     return;
   181   }
   183   mIsCompositorReady = true;
   184   mCompositor->SetTargetContext(aTarget);
   185   mTarget = aTarget;
   186 }
   188 bool
   189 LayerManagerComposite::EndEmptyTransaction(EndTransactionFlags aFlags)
   190 {
   191   NS_ASSERTION(mInTransaction, "Didn't call BeginTransaction?");
   192   if (!mRoot) {
   193     mInTransaction = false;
   194     mIsCompositorReady = false;
   195     return false;
   196   }
   198   EndTransaction(nullptr, nullptr);
   199   return true;
   200 }
   202 void
   203 LayerManagerComposite::EndTransaction(DrawThebesLayerCallback aCallback,
   204                                       void* aCallbackData,
   205                                       EndTransactionFlags aFlags)
   206 {
   207   NS_ASSERTION(mInTransaction, "Didn't call BeginTransaction?");
   208   NS_ASSERTION(!aCallback && !aCallbackData, "Not expecting callbacks here");
   209   mInTransaction = false;
   211   if (!mIsCompositorReady) {
   212     return;
   213   }
   214   mIsCompositorReady = false;
   216 #ifdef MOZ_LAYERS_HAVE_LOG
   217   MOZ_LAYERS_LOG(("  ----- (beginning paint)"));
   218   Log();
   219 #endif
   221   if (mDestroyed) {
   222     NS_WARNING("Call on destroyed layer manager");
   223     return;
   224   }
   226   if (mRoot && mClonedLayerTreeProperties) {
   227     nsIntRegion invalid =
   228       mClonedLayerTreeProperties->ComputeDifferences(mRoot, nullptr, &mGeometryChanged);
   229     mClonedLayerTreeProperties = nullptr;
   231     mInvalidRegion.Or(mInvalidRegion, invalid);
   232   } else {
   233     mInvalidRegion.Or(mInvalidRegion, mRenderBounds);
   234   }
   236   if (mRoot && !(aFlags & END_NO_IMMEDIATE_REDRAW)) {
   237     if (aFlags & END_NO_COMPOSITE) {
   238       // Apply pending tree updates before recomputing effective
   239       // properties.
   240       mRoot->ApplyPendingUpdatesToSubtree();
   241     }
   243     // The results of our drawing always go directly into a pixel buffer,
   244     // so we don't need to pass any global transform here.
   245     mRoot->ComputeEffectiveTransforms(gfx::Matrix4x4());
   247     Render();
   248     mGeometryChanged = false;
   249   }
   251   mCompositor->SetTargetContext(nullptr);
   252   mTarget = nullptr;
   254 #ifdef MOZ_LAYERS_HAVE_LOG
   255   Log();
   256   MOZ_LAYERS_LOG(("]----- EndTransaction"));
   257 #endif
   258 }
   260 TemporaryRef<DrawTarget>
   261 LayerManagerComposite::CreateOptimalMaskDrawTarget(const IntSize &aSize)
   262 {
   263   NS_RUNTIMEABORT("Should only be called on the drawing side");
   264   return nullptr;
   265 }
   267 already_AddRefed<ThebesLayer>
   268 LayerManagerComposite::CreateThebesLayer()
   269 {
   270   NS_RUNTIMEABORT("Should only be called on the drawing side");
   271   return nullptr;
   272 }
   274 already_AddRefed<ContainerLayer>
   275 LayerManagerComposite::CreateContainerLayer()
   276 {
   277   NS_RUNTIMEABORT("Should only be called on the drawing side");
   278   return nullptr;
   279 }
   281 already_AddRefed<ImageLayer>
   282 LayerManagerComposite::CreateImageLayer()
   283 {
   284   NS_RUNTIMEABORT("Should only be called on the drawing side");
   285   return nullptr;
   286 }
   288 already_AddRefed<ColorLayer>
   289 LayerManagerComposite::CreateColorLayer()
   290 {
   291   NS_RUNTIMEABORT("Should only be called on the drawing side");
   292   return nullptr;
   293 }
   295 already_AddRefed<CanvasLayer>
   296 LayerManagerComposite::CreateCanvasLayer()
   297 {
   298   NS_RUNTIMEABORT("Should only be called on the drawing side");
   299   return nullptr;
   300 }
   302 LayerComposite*
   303 LayerManagerComposite::RootLayer() const
   304 {
   305   if (mDestroyed) {
   306     NS_WARNING("Call on destroyed layer manager");
   307     return nullptr;
   308   }
   310   return ToLayerComposite(mRoot);
   311 }
   313 // Size of the builtin font.
   314 static const float FontHeight = 7.f;
   315 static const float FontWidth = 4.f;
   316 static const float FontStride = 4.f;
   318 // Scale the font when drawing it to the viewport for better readability.
   319 static const float FontScaleX = 2.f;
   320 static const float FontScaleY = 3.f;
   322 static void DrawDigits(unsigned int aValue,
   323 		       int aOffsetX, int aOffsetY,
   324                        Compositor* aCompositor,
   325 		       EffectChain& aEffectChain)
   326 {
   327   if (aValue > 999) {
   328     aValue = 999;
   329   }
   331   unsigned int divisor = 100;
   332   float textureWidth = FontWidth * 10;
   333   gfx::Float opacity = 1;
   334   gfx::Matrix4x4 transform;
   335   transform.Scale(FontScaleX, FontScaleY, 1);
   337   for (size_t n = 0; n < 3; ++n) {
   338     unsigned int digit = aValue % (divisor * 10) / divisor;
   339     divisor /= 10;
   341     RefPtr<TexturedEffect> texturedEffect = static_cast<TexturedEffect*>(aEffectChain.mPrimaryEffect.get());
   342     texturedEffect->mTextureCoords = Rect(float(digit * FontWidth) / textureWidth, 0, FontWidth / textureWidth, 1.0f);
   344     Rect drawRect = Rect(aOffsetX + n * FontWidth, aOffsetY, FontWidth, FontHeight);
   345     Rect clipRect = Rect(0, 0, 300, 100);
   346     aCompositor->DrawQuad(drawRect, clipRect,
   347 	aEffectChain, opacity, transform);
   348   }
   349 }
   351 void FPSState::DrawFPS(TimeStamp aNow,
   352                        unsigned int aFillRatio,
   353                        Compositor* aCompositor)
   354 {
   355   if (!mFPSTextureSource) {
   356     const char *text =
   357       "                                        "
   358       " XXX XX  XXX XXX X X XXX XXX XXX XXX XXX"
   359       " X X  X    X   X X X X   X     X X X X X"
   360       " X X  X  XXX XXX XXX XXX XXX   X XXX XXX"
   361       " X X  X  X     X   X   X X X   X X X   X"
   362       " XXX XXX XXX XXX   X XXX XXX   X XXX   X"
   363       "                                        ";
   365     // Convert the text encoding above to RGBA.
   366     int w = FontWidth * 10;
   367     int h = FontHeight;
   368     uint32_t* buf = (uint32_t *) malloc(w * h * sizeof(uint32_t));
   369     for (int i = 0; i < h; i++) {
   370       for (int j = 0; j < w; j++) {
   371         uint32_t purple = 0xfff000ff;
   372         uint32_t white  = 0xffffffff;
   373         buf[i * w + j] = (text[i * w + j] == ' ') ? purple : white;
   374       }
   375     }
   377    int bytesPerPixel = 4;
   378     RefPtr<DataSourceSurface> fpsSurface = Factory::CreateWrappingDataSourceSurface(
   379       reinterpret_cast<uint8_t*>(buf), w * bytesPerPixel, IntSize(w, h), SurfaceFormat::B8G8R8A8);
   380     mFPSTextureSource = aCompositor->CreateDataTextureSource();
   381     mFPSTextureSource->Update(fpsSurface);
   382   }
   384   EffectChain effectChain;
   385   effectChain.mPrimaryEffect = CreateTexturedEffect(SurfaceFormat::B8G8R8A8, mFPSTextureSource, Filter::POINT);
   387   unsigned int fps = unsigned(mCompositionFps.AddFrameAndGetFps(aNow));
   388   unsigned int txnFps = unsigned(mTransactionFps.GetFpsAt(aNow));
   390   DrawDigits(fps, 0, 0, aCompositor, effectChain);
   391   DrawDigits(txnFps, FontWidth * 4, 0, aCompositor, effectChain);
   392   DrawDigits(aFillRatio, FontWidth * 8, 0, aCompositor, effectChain);
   393 }
   395 static uint16_t sFrameCount = 0;
   396 void
   397 LayerManagerComposite::RenderDebugOverlay(const Rect& aBounds)
   398 {
   399   if (gfxPrefs::LayersDrawFPS()) {
   400     if (!mFPS) {
   401       mFPS = new FPSState();
   402     }
   404     float fillRatio = mCompositor->GetFillRatio();
   405     mFPS->DrawFPS(TimeStamp::Now(), unsigned(fillRatio), mCompositor);
   406   } else {
   407     mFPS = nullptr;
   408   }
   410   if (gfxPrefs::DrawFrameCounter()) {
   411     profiler_set_frame_number(sFrameCount);
   413     uint16_t frameNumber = sFrameCount;
   414     const uint16_t bitWidth = 3;
   415     float opacity = 1.0;
   416     gfx::Rect clip(0,0, bitWidth*16, bitWidth);
   417     for (size_t i = 0; i < 16; i++) {
   419       gfx::Color bitColor;
   420       if ((frameNumber >> i) & 0x1) {
   421         bitColor = gfx::Color(0, 0, 0, 1.0);
   422       } else {
   423         bitColor = gfx::Color(1.0, 1.0, 1.0, 1.0);
   424       }
   425       EffectChain effects;
   426       effects.mPrimaryEffect = new EffectSolidColor(bitColor);
   427       mCompositor->DrawQuad(gfx::Rect(bitWidth*i, 0, bitWidth, bitWidth),
   428                             clip,
   429                             effects,
   430                             opacity,
   431                             gfx::Matrix4x4());
   432     }
   433     // We intentionally overflow at 2^16.
   434     sFrameCount++;
   435   }
   436 }
   438 void
   439 LayerManagerComposite::Render()
   440 {
   441   PROFILER_LABEL("LayerManagerComposite", "Render");
   442   if (mDestroyed) {
   443     NS_WARNING("Call on destroyed layer manager");
   444     return;
   445   }
   447   if (gfxPrefs::LayersDump()) {
   448     this->Dump();
   449   }
   451   /** Our more efficient but less powerful alter ego, if one is available. */
   452   nsRefPtr<Composer2D> composer2D = mCompositor->GetWidget()->GetComposer2D();
   454   if (!mTarget && composer2D && composer2D->TryRender(mRoot, mWorldMatrix, mGeometryChanged)) {
   455     if (mFPS) {
   456       double fps = mFPS->mCompositionFps.AddFrameAndGetFps(TimeStamp::Now());
   457       if (gfxPrefs::LayersDrawFPS()) {
   458         printf_stderr("HWComposer: FPS is %g\n", fps);
   459       }
   460     }
   461     mCompositor->EndFrameForExternalComposition(mWorldMatrix);
   462     return;
   463   }
   465   {
   466     PROFILER_LABEL("LayerManagerComposite", "PreRender");
   467     if (!mCompositor->GetWidget()->PreRender(this)) {
   468       return;
   469     }
   470   }
   472   nsIntRect clipRect;
   473   Rect bounds(mRenderBounds.x, mRenderBounds.y, mRenderBounds.width, mRenderBounds.height);
   474   Rect actualBounds;
   475   if (mRoot->GetClipRect()) {
   476     clipRect = *mRoot->GetClipRect();
   477     WorldTransformRect(clipRect);
   478     Rect rect(clipRect.x, clipRect.y, clipRect.width, clipRect.height);
   479     mCompositor->BeginFrame(mInvalidRegion, &rect, mWorldMatrix, bounds, nullptr, &actualBounds);
   480   } else {
   481     gfx::Rect rect;
   482     mCompositor->BeginFrame(mInvalidRegion, nullptr, mWorldMatrix, bounds, &rect, &actualBounds);
   483     clipRect = nsIntRect(rect.x, rect.y, rect.width, rect.height);
   484   }
   486   // Reset the invalid region now that we've begun compositing.
   487   mInvalidRegion.SetEmpty();
   489   if (actualBounds.IsEmpty()) {
   490     mCompositor->GetWidget()->PostRender(this);
   491     return;
   492   }
   494   // Allow widget to render a custom background.
   495   mCompositor->GetWidget()->DrawWindowUnderlay(this, nsIntRect(actualBounds.x,
   496                                                                actualBounds.y,
   497                                                                actualBounds.width,
   498                                                                actualBounds.height));
   500   // Render our layers.
   501   RootLayer()->RenderLayer(clipRect);
   503   if (!mRegionToClear.IsEmpty()) {
   504     nsIntRegionRectIterator iter(mRegionToClear);
   505     const nsIntRect *r;
   506     while ((r = iter.Next())) {
   507       mCompositor->ClearRect(Rect(r->x, r->y, r->width, r->height));
   508     }
   509   }
   511   // Allow widget to render a custom foreground.
   512   mCompositor->GetWidget()->DrawWindowOverlay(this, nsIntRect(actualBounds.x,
   513                                                               actualBounds.y,
   514                                                               actualBounds.width,
   515                                                               actualBounds.height));
   517   // Debugging
   518   RenderDebugOverlay(actualBounds);
   520   {
   521     PROFILER_LABEL("LayerManagerComposite", "EndFrame");
   522     mCompositor->EndFrame();
   523     mCompositor->SetFBAcquireFence(mRoot);
   524   }
   526   mCompositor->GetWidget()->PostRender(this);
   528   RecordFrame();
   529 }
   531 void
   532 LayerManagerComposite::SetWorldTransform(const gfx::Matrix& aMatrix)
   533 {
   534   NS_ASSERTION(aMatrix.PreservesAxisAlignedRectangles(),
   535                "SetWorldTransform only accepts matrices that satisfy PreservesAxisAlignedRectangles");
   536   NS_ASSERTION(!aMatrix.HasNonIntegerScale(),
   537                "SetWorldTransform only accepts matrices with integer scale");
   539   mWorldMatrix = aMatrix;
   540 }
   542 gfx::Matrix&
   543 LayerManagerComposite::GetWorldTransform(void)
   544 {
   545   return mWorldMatrix;
   546 }
   548 void
   549 LayerManagerComposite::WorldTransformRect(nsIntRect& aRect)
   550 {
   551   gfx::Rect grect(aRect.x, aRect.y, aRect.width, aRect.height);
   552   grect = mWorldMatrix.TransformBounds(grect);
   553   aRect.SetRect(grect.X(), grect.Y(), grect.Width(), grect.Height());
   554 }
   556 static void
   557 SubtractTransformedRegion(nsIntRegion& aRegion,
   558                           const nsIntRegion& aRegionToSubtract,
   559                           const gfx3DMatrix& aTransform)
   560 {
   561   if (aRegionToSubtract.IsEmpty()) {
   562     return;
   563   }
   565   // For each rect in the region, find out its bounds in screen space and
   566   // subtract it from the screen region.
   567   nsIntRegionRectIterator it(aRegionToSubtract);
   568   while (const nsIntRect* rect = it.Next()) {
   569     gfxRect incompleteRect = aTransform.TransformBounds(gfxRect(*rect));
   570     aRegion.Sub(aRegion, nsIntRect(incompleteRect.x,
   571                                    incompleteRect.y,
   572                                    incompleteRect.width,
   573                                    incompleteRect.height));
   574   }
   575 }
   577 /* static */ void
   578 LayerManagerComposite::ComputeRenderIntegrityInternal(Layer* aLayer,
   579                                                       nsIntRegion& aScreenRegion,
   580                                                       nsIntRegion& aLowPrecisionScreenRegion,
   581                                                       const gfx3DMatrix& aTransform)
   582 {
   583   if (aLayer->GetOpacity() <= 0.f ||
   584       (aScreenRegion.IsEmpty() && aLowPrecisionScreenRegion.IsEmpty())) {
   585     return;
   586   }
   588   // If the layer's a container, recurse into all of its children
   589   ContainerLayer* container = aLayer->AsContainerLayer();
   590   if (container) {
   591     // Accumulate the transform of intermediate surfaces
   592     gfx3DMatrix transform = aTransform;
   593     if (container->UseIntermediateSurface()) {
   594       gfx::To3DMatrix(aLayer->GetEffectiveTransform(), transform);
   595       transform.PreMultiply(aTransform);
   596     }
   597     for (Layer* child = aLayer->GetFirstChild(); child;
   598          child = child->GetNextSibling()) {
   599       ComputeRenderIntegrityInternal(child, aScreenRegion, aLowPrecisionScreenRegion, transform);
   600     }
   601     return;
   602   }
   604   // Only thebes layers can be incomplete
   605   ThebesLayer* thebesLayer = aLayer->AsThebesLayer();
   606   if (!thebesLayer) {
   607     return;
   608   }
   610   // See if there's any incomplete rendering
   611   nsIntRegion incompleteRegion = aLayer->GetEffectiveVisibleRegion();
   612   incompleteRegion.Sub(incompleteRegion, thebesLayer->GetValidRegion());
   614   if (!incompleteRegion.IsEmpty()) {
   615     // Calculate the transform to get between screen and layer space
   616     gfx3DMatrix transformToScreen;
   617     To3DMatrix(aLayer->GetEffectiveTransform(), transformToScreen);
   618     transformToScreen.PreMultiply(aTransform);
   620     SubtractTransformedRegion(aScreenRegion, incompleteRegion, transformToScreen);
   622     // See if there's any incomplete low-precision rendering
   623     TiledLayerComposer* composer = nullptr;
   624     LayerComposite* shadow = aLayer->AsLayerComposite();
   625     if (shadow) {
   626       composer = shadow->GetTiledLayerComposer();
   627       if (composer) {
   628         incompleteRegion.Sub(incompleteRegion, composer->GetValidLowPrecisionRegion());
   629         if (!incompleteRegion.IsEmpty()) {
   630           SubtractTransformedRegion(aLowPrecisionScreenRegion, incompleteRegion, transformToScreen);
   631         }
   632       }
   633     }
   635     // If we can't get a valid low precision region, assume it's the same as
   636     // the high precision region.
   637     if (!composer) {
   638       SubtractTransformedRegion(aLowPrecisionScreenRegion, incompleteRegion, transformToScreen);
   639     }
   640   }
   641 }
   643 #ifdef MOZ_ANDROID_OMTC
   644 static float
   645 GetDisplayportCoverage(const CSSRect& aDisplayPort,
   646                        const gfx3DMatrix& aTransformToScreen,
   647                        const nsIntRect& aScreenRect)
   648 {
   649   gfxRect transformedDisplayport =
   650     aTransformToScreen.TransformBounds(gfxRect(aDisplayPort.x,
   651                                                aDisplayPort.y,
   652                                                aDisplayPort.width,
   653                                                aDisplayPort.height));
   654   transformedDisplayport.RoundOut();
   655   nsIntRect displayport = nsIntRect(transformedDisplayport.x,
   656                                     transformedDisplayport.y,
   657                                     transformedDisplayport.width,
   658                                     transformedDisplayport.height);
   659   if (!displayport.Contains(aScreenRect)) {
   660     nsIntRegion coveredRegion;
   661     coveredRegion.And(aScreenRect, displayport);
   662     return coveredRegion.Area() / (float)(aScreenRect.width * aScreenRect.height);
   663   }
   665   return 1.0f;
   666 }
   667 #endif // MOZ_ANDROID_OMTC
   669 float
   670 LayerManagerComposite::ComputeRenderIntegrity()
   671 {
   672   // We only ever have incomplete rendering when progressive tiles are enabled.
   673   Layer* root = GetRoot();
   674   if (!gfxPrefs::UseProgressiveTilePainting() || !root) {
   675     return 1.f;
   676   }
   678   const FrameMetrics& rootMetrics = root->AsContainerLayer()->GetFrameMetrics();
   679   nsIntRect screenRect(rootMetrics.mCompositionBounds.x,
   680                        rootMetrics.mCompositionBounds.y,
   681                        rootMetrics.mCompositionBounds.width,
   682                        rootMetrics.mCompositionBounds.height);
   684   float lowPrecisionMultiplier = 1.0f;
   685   float highPrecisionMultiplier = 1.0f;
   687 #ifdef MOZ_ANDROID_OMTC
   688   // Use the transform on the primary scrollable layer and its FrameMetrics
   689   // to find out how much of the viewport the current displayport covers
   690   Layer* primaryScrollable = GetPrimaryScrollableLayer();
   691   if (primaryScrollable) {
   692     // This is derived from the code in
   693     // AsyncCompositionManager::TransformScrollableLayer
   694     const FrameMetrics& metrics = primaryScrollable->AsContainerLayer()->GetFrameMetrics();
   695     gfx3DMatrix transform;
   696     gfx::To3DMatrix(primaryScrollable->GetEffectiveTransform(), transform);
   697     transform.ScalePost(metrics.mResolution.scale, metrics.mResolution.scale, 1);
   699     // Clip the screen rect to the document bounds
   700     gfxRect documentBounds =
   701       transform.TransformBounds(gfxRect(metrics.mScrollableRect.x - metrics.GetScrollOffset().x,
   702                                         metrics.mScrollableRect.y - metrics.GetScrollOffset().y,
   703                                         metrics.mScrollableRect.width,
   704                                         metrics.mScrollableRect.height));
   705     documentBounds.RoundOut();
   706     screenRect = screenRect.Intersect(nsIntRect(documentBounds.x, documentBounds.y,
   707                                                 documentBounds.width, documentBounds.height));
   709     // If the screen rect is empty, the user has scrolled entirely into
   710     // over-scroll and so we can be considered to have full integrity.
   711     if (screenRect.IsEmpty()) {
   712       return 1.0f;
   713     }
   715     // Work out how much of the critical display-port covers the screen
   716     bool hasLowPrecision = false;
   717     if (!metrics.mCriticalDisplayPort.IsEmpty()) {
   718       hasLowPrecision = true;
   719       highPrecisionMultiplier =
   720         GetDisplayportCoverage(metrics.mCriticalDisplayPort, transform, screenRect);
   721     }
   723     // Work out how much of the display-port covers the screen
   724     if (!metrics.mDisplayPort.IsEmpty()) {
   725       if (hasLowPrecision) {
   726         lowPrecisionMultiplier =
   727           GetDisplayportCoverage(metrics.mDisplayPort, transform, screenRect);
   728       } else {
   729         lowPrecisionMultiplier = highPrecisionMultiplier =
   730           GetDisplayportCoverage(metrics.mDisplayPort, transform, screenRect);
   731       }
   732     }
   733   }
   735   // If none of the screen is covered, we have zero integrity.
   736   if (highPrecisionMultiplier <= 0.0f && lowPrecisionMultiplier <= 0.0f) {
   737     return 0.0f;
   738   }
   739 #endif // MOZ_ANDROID_OMTC
   741   nsIntRegion screenRegion(screenRect);
   742   nsIntRegion lowPrecisionScreenRegion(screenRect);
   743   gfx3DMatrix transform;
   744   ComputeRenderIntegrityInternal(root, screenRegion,
   745                                  lowPrecisionScreenRegion, transform);
   747   if (!screenRegion.IsEqual(screenRect)) {
   748     // Calculate the area of the region. All rects in an nsRegion are
   749     // non-overlapping.
   750     float screenArea = screenRect.width * screenRect.height;
   751     float highPrecisionIntegrity = screenRegion.Area() / screenArea;
   752     float lowPrecisionIntegrity = 1.f;
   753     if (!lowPrecisionScreenRegion.IsEqual(screenRect)) {
   754       lowPrecisionIntegrity = lowPrecisionScreenRegion.Area() / screenArea;
   755     }
   757     return ((highPrecisionIntegrity * highPrecisionMultiplier) +
   758             (lowPrecisionIntegrity * lowPrecisionMultiplier)) / 2;
   759   }
   761   return 1.f;
   762 }
   764 already_AddRefed<ThebesLayerComposite>
   765 LayerManagerComposite::CreateThebesLayerComposite()
   766 {
   767   if (mDestroyed) {
   768     NS_WARNING("Call on destroyed layer manager");
   769     return nullptr;
   770   }
   771   return nsRefPtr<ThebesLayerComposite>(new ThebesLayerComposite(this)).forget();
   772 }
   774 already_AddRefed<ContainerLayerComposite>
   775 LayerManagerComposite::CreateContainerLayerComposite()
   776 {
   777   if (mDestroyed) {
   778     NS_WARNING("Call on destroyed layer manager");
   779     return nullptr;
   780   }
   781   return nsRefPtr<ContainerLayerComposite>(new ContainerLayerComposite(this)).forget();
   782 }
   784 already_AddRefed<ImageLayerComposite>
   785 LayerManagerComposite::CreateImageLayerComposite()
   786 {
   787   if (mDestroyed) {
   788     NS_WARNING("Call on destroyed layer manager");
   789     return nullptr;
   790   }
   791   return nsRefPtr<ImageLayerComposite>(new ImageLayerComposite(this)).forget();
   792 }
   794 already_AddRefed<ColorLayerComposite>
   795 LayerManagerComposite::CreateColorLayerComposite()
   796 {
   797   if (LayerManagerComposite::mDestroyed) {
   798     NS_WARNING("Call on destroyed layer manager");
   799     return nullptr;
   800   }
   801   return nsRefPtr<ColorLayerComposite>(new ColorLayerComposite(this)).forget();
   802 }
   804 already_AddRefed<CanvasLayerComposite>
   805 LayerManagerComposite::CreateCanvasLayerComposite()
   806 {
   807   if (LayerManagerComposite::mDestroyed) {
   808     NS_WARNING("Call on destroyed layer manager");
   809     return nullptr;
   810   }
   811   return nsRefPtr<CanvasLayerComposite>(new CanvasLayerComposite(this)).forget();
   812 }
   814 already_AddRefed<RefLayerComposite>
   815 LayerManagerComposite::CreateRefLayerComposite()
   816 {
   817   if (LayerManagerComposite::mDestroyed) {
   818     NS_WARNING("Call on destroyed layer manager");
   819     return nullptr;
   820   }
   821   return nsRefPtr<RefLayerComposite>(new RefLayerComposite(this)).forget();
   822 }
   824 LayerManagerComposite::AutoAddMaskEffect::AutoAddMaskEffect(Layer* aMaskLayer,
   825                                                             EffectChain& aEffects,
   826                                                             bool aIs3D)
   827   : mCompositable(nullptr)
   828 {
   829   if (!aMaskLayer) {
   830     return;
   831   }
   833   mCompositable = ToLayerComposite(aMaskLayer)->GetCompositableHost();
   834   if (!mCompositable) {
   835     NS_WARNING("Mask layer with no compositable host");
   836     return;
   837   }
   839   if (!mCompositable->AddMaskEffect(aEffects, aMaskLayer->GetEffectiveTransform(), aIs3D)) {
   840     mCompositable = nullptr;
   841   }
   842 }
   844 LayerManagerComposite::AutoAddMaskEffect::~AutoAddMaskEffect()
   845 {
   846   if (!mCompositable) {
   847     return;
   848   }
   850   mCompositable->RemoveMaskEffect();
   851 }
   853 TemporaryRef<DrawTarget>
   854 LayerManagerComposite::CreateDrawTarget(const IntSize &aSize,
   855                                         SurfaceFormat aFormat)
   856 {
   857 #ifdef XP_MACOSX
   858   // We don't want to accelerate if the surface is too small which indicates
   859   // that it's likely used for an icon/static image. We also don't want to
   860   // accelerate anything that is above the maximum texture size of weakest gpu.
   861   // Safari uses 5000 area as the minimum for acceleration, we decided 64^2 is more logical.
   862   bool useAcceleration = aSize.width <= 4096 && aSize.height <= 4096 &&
   863                          aSize.width > 64 && aSize.height > 64 &&
   864                          gfxPlatformMac::GetPlatform()->UseAcceleratedCanvas();
   865   if (useAcceleration) {
   866     return Factory::CreateDrawTarget(BackendType::COREGRAPHICS_ACCELERATED,
   867                                      aSize, aFormat);
   868   }
   869 #endif
   870   return LayerManager::CreateDrawTarget(aSize, aFormat);
   871 }
   873 LayerComposite::LayerComposite(LayerManagerComposite *aManager)
   874   : mCompositeManager(aManager)
   875   , mCompositor(aManager->GetCompositor())
   876   , mShadowOpacity(1.0)
   877   , mUseShadowClipRect(false)
   878   , mShadowTransformSetByAnimation(false)
   879   , mDestroyed(false)
   880   , mLayerComposited(false)
   881 { }
   883 LayerComposite::~LayerComposite()
   884 {
   885 }
   887 void
   888 LayerComposite::Destroy()
   889 {
   890   if (!mDestroyed) {
   891     mDestroyed = true;
   892     CleanupResources();
   893   }
   894 }
   896 bool
   897 LayerManagerComposite::CanUseCanvasLayerForSize(const IntSize &aSize)
   898 {
   899   return mCompositor->CanUseCanvasLayerForSize(gfx::IntSize(aSize.width,
   900                                                             aSize.height));
   901 }
   903 void
   904 LayerManagerComposite::NotifyShadowTreeTransaction()
   905 {
   906   if (mFPS) {
   907     mFPS->NotifyShadowTreeTransaction();
   908   }
   909 }
   911 #ifndef MOZ_HAVE_PLATFORM_SPECIFIC_LAYER_BUFFERS
   913 /*static*/ bool
   914 LayerManagerComposite::SupportsDirectTexturing()
   915 {
   916   return false;
   917 }
   919 /*static*/ void
   920 LayerManagerComposite::PlatformSyncBeforeReplyUpdate()
   921 {
   922 }
   924 #endif  // !defined(MOZ_HAVE_PLATFORM_SPECIFIC_LAYER_BUFFERS)
   926 } /* layers */
   927 } /* mozilla */

mercurial