gfx/layers/ReadbackProcessor.cpp

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

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

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

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

mercurial