LCOV - code coverage report
Current view: top level - gfx/layers - ReadbackProcessor.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 7 94 7.4 %
Date: 2017-07-14 16:53:18 Functions: 2 5 40.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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/. */
       5             : 
       6             : #include "ReadbackProcessor.h"
       7             : #include <sys/types.h>                  // for int32_t
       8             : #include "Layers.h"                     // for Layer, PaintedLayer, etc
       9             : #include "ReadbackLayer.h"              // for ReadbackLayer, ReadbackSink
      10             : #include "UnitTransforms.h"             // for ViewAs
      11             : #include "Units.h"                      // for ParentLayerIntRect
      12             : #include "gfxContext.h"                 // for gfxContext
      13             : #include "gfxUtils.h"
      14             : #include "gfxRect.h"                    // for gfxRect
      15             : #include "mozilla/gfx/2D.h"
      16             : #include "mozilla/gfx/BasePoint.h"      // for BasePoint
      17             : #include "mozilla/gfx/BaseRect.h"       // for BaseRect
      18             : #include "mozilla/gfx/Point.h"          // for Intsize
      19             : #include "nsDebug.h"                    // for NS_ASSERTION
      20             : #include "nsISupportsImpl.h"            // for gfxContext::Release, etc
      21             : #include "nsPoint.h"                    // for nsIntPoint
      22             : #include "nsRegion.h"                   // for nsIntRegion
      23             : 
      24             : using namespace mozilla::gfx;
      25             : 
      26             : namespace mozilla {
      27             : namespace layers {
      28             : 
      29             : void
      30          57 : ReadbackProcessor::BuildUpdates(ContainerLayer* aContainer)
      31             : {
      32          57 :   NS_ASSERTION(mAllUpdates.IsEmpty(), "Some updates not processed?");
      33             : 
      34          57 :   if (!aContainer->mMayHaveReadbackChild)
      35          57 :     return;
      36             : 
      37           0 :   aContainer->mMayHaveReadbackChild = false;
      38             :   // go backwards so the updates read from earlier layers are later in the
      39             :   // array.
      40           0 :   for (Layer* l = aContainer->GetLastChild(); l; l = l->GetPrevSibling()) {
      41           0 :     if (l->GetType() == Layer::TYPE_READBACK) {
      42           0 :       aContainer->mMayHaveReadbackChild = true;
      43           0 :       BuildUpdatesForLayer(static_cast<ReadbackLayer*>(l));
      44             :     }
      45             :   }
      46             : }
      47             : 
      48             : static Layer*
      49           0 : FindBackgroundLayer(ReadbackLayer* aLayer, nsIntPoint* aOffset)
      50             : {
      51           0 :   gfx::Matrix transform;
      52           0 :   if (!aLayer->GetTransform().Is2D(&transform) ||
      53           0 :       transform.HasNonIntegerTranslation())
      54           0 :     return nullptr;
      55           0 :   nsIntPoint transformOffset(int32_t(transform._31), int32_t(transform._32));
      56             : 
      57           0 :   for (Layer* l = aLayer->GetPrevSibling(); l; l = l->GetPrevSibling()) {
      58           0 :     gfx::Matrix backgroundTransform;
      59           0 :     if (!l->GetTransform().Is2D(&backgroundTransform) ||
      60           0 :         gfx::ThebesMatrix(backgroundTransform).HasNonIntegerTranslation())
      61           0 :       return nullptr;
      62             : 
      63           0 :     nsIntPoint backgroundOffset(int32_t(backgroundTransform._31), int32_t(backgroundTransform._32));
      64           0 :     IntRect rectInBackground(transformOffset - backgroundOffset, aLayer->GetSize());
      65           0 :     const nsIntRegion visibleRegion = l->GetLocalVisibleRegion().ToUnknownRegion();
      66           0 :     if (!visibleRegion.Intersects(rectInBackground))
      67           0 :       continue;
      68             :     // Since l is present in the background, from here on we either choose l
      69             :     // or nothing.
      70           0 :     if (!visibleRegion.Contains(rectInBackground))
      71           0 :       return nullptr;
      72             : 
      73           0 :     if (l->GetEffectiveOpacity() != 1.0 ||
      74           0 :         l->HasMaskLayers() ||
      75           0 :         !(l->GetContentFlags() & Layer::CONTENT_OPAQUE))
      76             :     {
      77           0 :       return nullptr;
      78             :     }
      79             : 
      80             :     // cliprects are post-transform
      81           0 :     const Maybe<ParentLayerIntRect>& clipRect = l->GetLocalClipRect();
      82           0 :     if (clipRect && !clipRect->Contains(ViewAs<ParentLayerPixel>(IntRect(transformOffset, aLayer->GetSize()))))
      83           0 :       return nullptr;
      84             : 
      85           0 :     Layer::LayerType type = l->GetType();
      86           0 :     if (type != Layer::TYPE_COLOR && type != Layer::TYPE_PAINTED)
      87           0 :       return nullptr;
      88             : 
      89           0 :     *aOffset = backgroundOffset - transformOffset;
      90           0 :     return l;
      91             :   }
      92             : 
      93           0 :   return nullptr;
      94             : }
      95             : 
      96             : void
      97           0 : ReadbackProcessor::BuildUpdatesForLayer(ReadbackLayer* aLayer)
      98             : {
      99           0 :   if (!aLayer->mSink)
     100           0 :     return;
     101             : 
     102           0 :   nsIntPoint offset;
     103           0 :   Layer* newBackground = FindBackgroundLayer(aLayer, &offset);
     104           0 :   if (!newBackground) {
     105           0 :     aLayer->SetUnknown();
     106           0 :     return;
     107             :   }
     108             : 
     109           0 :   if (newBackground->GetType() == Layer::TYPE_COLOR) {
     110           0 :     ColorLayer* colorLayer = static_cast<ColorLayer*>(newBackground);
     111           0 :     if (aLayer->mBackgroundColor != colorLayer->GetColor()) {
     112           0 :       aLayer->mBackgroundLayer = nullptr;
     113           0 :       aLayer->mBackgroundColor = colorLayer->GetColor();
     114           0 :       NS_ASSERTION(aLayer->mBackgroundColor.a == 1.f,
     115             :                    "Color layer said it was opaque!");
     116             :       RefPtr<DrawTarget> dt =
     117           0 :           aLayer->mSink->BeginUpdate(aLayer->GetRect(),
     118           0 :                                      aLayer->AllocateSequenceNumber());
     119           0 :       if (dt) {
     120           0 :         ColorPattern color(ToDeviceColor(aLayer->mBackgroundColor));
     121           0 :         IntSize size = aLayer->GetSize();
     122           0 :         dt->FillRect(Rect(0, 0, size.width, size.height), color);
     123           0 :         aLayer->mSink->EndUpdate(aLayer->GetRect());
     124             :       }
     125             :     }
     126             :   } else {
     127           0 :     NS_ASSERTION(newBackground->AsPaintedLayer(), "Must be PaintedLayer");
     128           0 :     PaintedLayer* paintedLayer = static_cast<PaintedLayer*>(newBackground);
     129             :     // updateRect is relative to the PaintedLayer
     130           0 :     IntRect updateRect = aLayer->GetRect() - offset;
     131           0 :     if (paintedLayer != aLayer->mBackgroundLayer ||
     132           0 :         offset != aLayer->mBackgroundLayerOffset) {
     133           0 :       aLayer->mBackgroundLayer = paintedLayer;
     134           0 :       aLayer->mBackgroundLayerOffset = offset;
     135           0 :       aLayer->mBackgroundColor = Color();
     136           0 :       paintedLayer->SetUsedForReadback(true);
     137             :     } else {
     138           0 :       nsIntRegion invalid;
     139           0 :       invalid.Sub(updateRect, paintedLayer->GetValidRegion());
     140           0 :       updateRect = invalid.GetBounds();
     141             :     }
     142             : 
     143           0 :     Update update = { aLayer, updateRect, aLayer->AllocateSequenceNumber() };
     144           0 :     mAllUpdates.AppendElement(update);
     145             :   }
     146             : }
     147             : 
     148             : void
     149           0 : ReadbackProcessor::GetPaintedLayerUpdates(PaintedLayer* aLayer,
     150             :                                          nsTArray<Update>* aUpdates,
     151             :                                          nsIntRegion* aUpdateRegion)
     152             : {
     153             :   // All PaintedLayers used for readback are in mAllUpdates (some possibly
     154             :   // with an empty update rect).
     155           0 :   aLayer->SetUsedForReadback(false);
     156           0 :   if (aUpdateRegion) {
     157           0 :     aUpdateRegion->SetEmpty();
     158             :   }
     159           0 :   for (uint32_t i = mAllUpdates.Length(); i > 0; --i) {
     160           0 :     const Update& update = mAllUpdates[i - 1];
     161           0 :     if (update.mLayer->mBackgroundLayer == aLayer) {
     162           0 :       aLayer->SetUsedForReadback(true);
     163             :       // Don't bother asking for updates if we have an empty update rect.
     164           0 :       if (!update.mUpdateRect.IsEmpty()) {
     165           0 :         aUpdates->AppendElement(update);
     166           0 :         if (aUpdateRegion) {
     167           0 :           aUpdateRegion->Or(*aUpdateRegion, update.mUpdateRect);
     168             :         }
     169             :       }
     170           0 :       mAllUpdates.RemoveElementAt(i - 1);
     171             :     }
     172             :   }
     173           0 : }
     174             : 
     175         258 : ReadbackProcessor::~ReadbackProcessor()
     176             : {
     177         129 :   for (uint32_t i = mAllUpdates.Length(); i > 0; --i) {
     178           0 :     const Update& update = mAllUpdates[i - 1];
     179             :     // Unprocessed update. Notify the readback sink that this content is
     180             :     // unknown.
     181           0 :     update.mLayer->SetUnknown();
     182             :   }
     183         129 : }
     184             : 
     185             : } // namespace layers
     186             : } // namespace mozilla

Generated by: LCOV version 1.13