Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/gfx/layers/basic/BasicContainerLayer.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "BasicContainerLayer.h"
8
#include <sys/types.h>                  // for int32_t
9
#include "BasicLayersImpl.h"            // for ToData
10
#include "basic/BasicImplData.h"        // for BasicImplData
11
#include "basic/BasicLayers.h"          // for BasicLayerManager
12
#include "mozilla/gfx/BaseRect.h"       // for BaseRect
13
#include "mozilla/mozalloc.h"           // for operator new
14
#include "nsCOMPtr.h"                   // for already_AddRefed
15
#include "nsISupportsImpl.h"            // for Layer::AddRef, etc
16
#include "nsPoint.h"                    // for nsIntPoint
17
#include "nsRegion.h"                   // for nsIntRegion
18
#include "ReadbackProcessor.h"
19
20
using namespace mozilla::gfx;
21
22
namespace mozilla {
23
namespace layers {
24
25
BasicContainerLayer::~BasicContainerLayer()
26
0
{
27
0
  ContainerLayer::RemoveAllChildren();
28
0
  MOZ_COUNT_DTOR(BasicContainerLayer);
29
0
}
30
31
void
32
BasicContainerLayer::ComputeEffectiveTransforms(const Matrix4x4& aTransformToSurface)
33
0
{
34
0
  // We push groups for container layers if we need to, which always
35
0
  // are aligned in device space, so it doesn't really matter how we snap
36
0
  // containers.
37
0
  Matrix residual;
38
0
  Matrix4x4 transformToSurface = aTransformToSurface;
39
0
  bool participate3DCtx = Extend3DContext() || Is3DContextLeaf();
40
0
  if (!participate3DCtx &&
41
0
      GetContentFlags() & CONTENT_BACKFACE_HIDDEN) {
42
0
    // For backface-hidden layers
43
0
    transformToSurface.ProjectTo2D();
44
0
  }
45
0
  Matrix4x4 idealTransform = GetLocalTransform() * transformToSurface;
46
0
  if (!participate3DCtx &&
47
0
      !(GetContentFlags() & CONTENT_BACKFACE_HIDDEN)) {
48
0
    // For non-backface-hidden layers,
49
0
    // 3D components are required to handle CONTENT_BACKFACE_HIDDEN.
50
0
    idealTransform.ProjectTo2D();
51
0
  }
52
0
53
0
  if (!idealTransform.CanDraw2D()) {
54
0
    if (!Extend3DContext()) {
55
0
      mEffectiveTransform = idealTransform;
56
0
      ComputeEffectiveTransformsForChildren(Matrix4x4());
57
0
      ComputeEffectiveTransformForMaskLayers(Matrix4x4());
58
0
      mUseIntermediateSurface = true;
59
0
      return;
60
0
    }
61
0
62
0
    mEffectiveTransform = idealTransform;
63
0
    ComputeEffectiveTransformsForChildren(idealTransform);
64
0
    ComputeEffectiveTransformForMaskLayers(idealTransform);
65
0
    mUseIntermediateSurface = false;
66
0
    return;
67
0
  }
68
0
69
0
  // With 2D transform or extended 3D context.
70
0
71
0
  Layer* child = GetFirstChild();
72
0
  bool hasSingleBlendingChild = false;
73
0
  if (!HasMultipleChildren() && child) {
74
0
    hasSingleBlendingChild = child->GetMixBlendMode() != CompositionOp::OP_OVER;
75
0
  }
76
0
77
0
  /* If we have a single childand it is not blending,, it can just inherit our opacity,
78
0
   * otherwise we need a PushGroup and we need to mark ourselves as using
79
0
   * an intermediate surface so our children don't inherit our opacity
80
0
   * via GetEffectiveOpacity.
81
0
   * Having a mask layer always forces our own push group
82
0
   * Having a blend mode also always forces our own push group
83
0
   */
84
0
  mUseIntermediateSurface =
85
0
    GetMaskLayer() ||
86
0
    GetForceIsolatedGroup() ||
87
0
    (GetMixBlendMode() != CompositionOp::OP_OVER && HasMultipleChildren()) ||
88
0
    (GetEffectiveOpacity() != 1.0 && ((HasMultipleChildren() && !Extend3DContext()) || hasSingleBlendingChild));
89
0
90
0
  mEffectiveTransform =
91
0
    !mUseIntermediateSurface ?
92
0
    idealTransform :
93
0
    (!(GetContentFlags() & CONTENT_BACKFACE_HIDDEN) ?
94
0
     SnapTransformTranslation(idealTransform, &residual) :
95
0
     SnapTransformTranslation3D(idealTransform, &residual));
96
0
  Matrix4x4 childTransformToSurface =
97
0
    (!mUseIntermediateSurface ||
98
0
     (mUseIntermediateSurface && !Extend3DContext() /* 2D */)) ?
99
0
    idealTransform : Matrix4x4::From2D(residual);
100
0
  ComputeEffectiveTransformsForChildren(childTransformToSurface);
101
0
102
0
  ComputeEffectiveTransformForMaskLayers(aTransformToSurface);
103
0
}
104
105
bool
106
BasicContainerLayer::ChildrenPartitionVisibleRegion(const gfx::IntRect& aInRect)
107
0
{
108
0
  Matrix transform;
109
0
  if (!GetEffectiveTransform().CanDraw2D(&transform) ||
110
0
      ThebesMatrix(transform).HasNonIntegerTranslation())
111
0
    return false;
112
0
113
0
  nsIntPoint offset(int32_t(transform._31), int32_t(transform._32));
114
0
  gfx::IntRect rect = aInRect.Intersect(GetLocalVisibleRegion().GetBounds().ToUnknownRect() + offset);
115
0
  nsIntRegion covered;
116
0
117
0
  for (Layer* l = mFirstChild; l; l = l->GetNextSibling()) {
118
0
    if (ToData(l)->IsHidden())
119
0
      continue;
120
0
121
0
    Matrix childTransform;
122
0
    if (!l->GetEffectiveTransform().CanDraw2D(&childTransform) ||
123
0
        ThebesMatrix(childTransform).HasNonIntegerTranslation() ||
124
0
        l->GetEffectiveOpacity() != 1.0)
125
0
      return false;
126
0
    nsIntRegion childRegion = l->GetLocalVisibleRegion().ToUnknownRegion();
127
0
    childRegion.MoveBy(int32_t(childTransform._31), int32_t(childTransform._32));
128
0
    childRegion.And(childRegion, rect);
129
0
    if (l->GetClipRect()) {
130
0
      childRegion.And(childRegion, l->GetClipRect()->ToUnknownRect() + offset);
131
0
    }
132
0
    nsIntRegion intersection;
133
0
    intersection.And(covered, childRegion);
134
0
    if (!intersection.IsEmpty())
135
0
      return false;
136
0
    covered.Or(covered, childRegion);
137
0
  }
138
0
139
0
  return covered.Contains(rect);
140
0
}
141
142
void
143
BasicContainerLayer::Validate(LayerManager::DrawPaintedLayerCallback aCallback,
144
                              void* aCallbackData,
145
                              ReadbackProcessor* aReadback)
146
0
{
147
0
  ReadbackProcessor readback;
148
0
  if (BasicManager()->IsRetained()) {
149
0
    readback.BuildUpdates(this);
150
0
  }
151
0
  for (Layer* l = mFirstChild; l; l = l->GetNextSibling()) {
152
0
    BasicImplData* data = ToData(l);
153
0
    data->Validate(aCallback, aCallbackData, &readback);
154
0
    if (l->GetMaskLayer()) {
155
0
      data = ToData(l->GetMaskLayer());
156
0
      data->Validate(aCallback, aCallbackData, nullptr);
157
0
    }
158
0
  }
159
0
}
160
161
already_AddRefed<ContainerLayer>
162
BasicLayerManager::CreateContainerLayer()
163
0
{
164
0
  NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
165
0
  RefPtr<ContainerLayer> layer = new BasicContainerLayer(this);
166
0
  return layer.forget();
167
0
}
168
169
} // namespace layers
170
} // namespace mozilla