Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/gfx/layers/basic/BasicPaintedLayer.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 "BasicPaintedLayer.h"
8
#include <stdint.h>                     // for uint32_t
9
#include "GeckoProfiler.h"              // for AUTO_PROFILER_LABEL
10
#include "ReadbackLayer.h"              // for ReadbackLayer, ReadbackSink
11
#include "ReadbackProcessor.h"          // for ReadbackProcessor::Update, etc
12
#include "RenderTrace.h"                // for RenderTraceInvalidateEnd, etc
13
#include "BasicLayersImpl.h"            // for AutoMaskData, etc
14
#include "gfxContext.h"                 // for gfxContext, etc
15
#include "gfxRect.h"                    // for gfxRect
16
#include "gfxUtils.h"                   // for gfxUtils
17
#include "mozilla/gfx/2D.h"             // for DrawTarget
18
#include "mozilla/gfx/BaseRect.h"       // for BaseRect
19
#include "mozilla/gfx/Matrix.h"         // for Matrix
20
#include "mozilla/gfx/Rect.h"           // for Rect, IntRect
21
#include "mozilla/gfx/Types.h"          // for Float, etc
22
#include "mozilla/layers/LayersTypes.h"
23
#include "nsCOMPtr.h"                   // for already_AddRefed
24
#include "nsISupportsImpl.h"            // for gfxContext::Release, etc
25
#include "nsPoint.h"                    // for nsIntPoint
26
#include "nsRect.h"                     // for mozilla::gfx::IntRect
27
#include "nsTArray.h"                   // for nsTArray, nsTArray_Impl
28
#include "AutoMaskData.h"
29
#include "gfx2DGlue.h"
30
31
namespace mozilla {
32
namespace layers {
33
34
using namespace mozilla::gfx;
35
36
static nsIntRegion
37
IntersectWithClip(const nsIntRegion& aRegion, gfxContext* aContext)
38
0
{
39
0
  gfxRect clip = aContext->GetClipExtents();
40
0
  nsIntRegion result;
41
0
  result.And(aRegion, IntRect::RoundOut(clip.X(), clip.Y(),
42
0
                                        clip.Width(), clip.Height()));
43
0
  return result;
44
0
}
45
46
void
47
BasicPaintedLayer::PaintThebes(gfxContext* aContext,
48
                              Layer* aMaskLayer,
49
                              LayerManager::DrawPaintedLayerCallback aCallback,
50
                              void* aCallbackData)
51
0
{
52
0
  AUTO_PROFILER_LABEL("BasicPaintedLayer::PaintThebes", GRAPHICS);
53
0
54
0
  NS_ASSERTION(BasicManager()->InDrawing(),
55
0
               "Can only draw in drawing phase");
56
0
57
0
  float opacity = GetEffectiveOpacity();
58
0
  CompositionOp effectiveOperator = GetEffectiveOperator(this);
59
0
60
0
  if (!BasicManager()->IsRetained()) {
61
0
    ClearValidRegion();
62
0
    mContentClient->Clear();
63
0
64
0
    nsIntRegion toDraw = IntersectWithClip(GetLocalVisibleRegion().ToUnknownRegion(), aContext);
65
0
66
0
    RenderTraceInvalidateStart(this, "FFFF00", toDraw.GetBounds());
67
0
68
0
    if (!toDraw.IsEmpty() && !IsHidden()) {
69
0
      if (!aCallback) {
70
0
        BasicManager()->SetTransactionIncomplete();
71
0
        return;
72
0
      }
73
0
74
0
      aContext->Save();
75
0
76
0
      bool needsGroup = opacity != 1.0 ||
77
0
                        effectiveOperator != CompositionOp::OP_OVER ||
78
0
                        aMaskLayer;
79
0
      RefPtr<gfxContext> context = nullptr;
80
0
      BasicLayerManager::PushedGroup group;
81
0
      bool availableGroup = false;
82
0
83
0
      if (needsGroup) {
84
0
        availableGroup =
85
0
            BasicManager()->PushGroupForLayer(aContext, this, toDraw, group);
86
0
        if (availableGroup) {
87
0
          context = group.mGroupTarget;
88
0
        }
89
0
      } else {
90
0
        context = aContext;
91
0
      }
92
0
      if (context) {
93
0
        DrawTarget* target = context->GetDrawTarget();
94
0
        bool oldAA = target->GetPermitSubpixelAA();
95
0
        SetAntialiasingFlags(this, target);
96
0
        aCallback(this, context, toDraw, toDraw, DrawRegionClip::NONE,
97
0
                  nsIntRegion(), aCallbackData);
98
0
        target->SetPermitSubpixelAA(oldAA);
99
0
      }
100
0
      if (needsGroup && availableGroup) {
101
0
        BasicManager()->PopGroupForLayer(group);
102
0
      }
103
0
104
0
      aContext->Restore();
105
0
    }
106
0
107
0
    RenderTraceInvalidateEnd(this, "FFFF00");
108
0
    return;
109
0
  }
110
0
111
0
  if (BasicManager()->IsTransactionIncomplete())
112
0
    return;
113
0
114
0
  gfxRect clipExtents;
115
0
  clipExtents = aContext->GetClipExtents();
116
0
117
0
  // Pull out the mask surface and transform here, because the mask
118
0
  // is internal to basic layers
119
0
  AutoMoz2DMaskData mask;
120
0
  SourceSurface* maskSurface = nullptr;
121
0
  Matrix maskTransform;
122
0
  if (GetMaskData(aMaskLayer, aContext->GetDeviceOffset(), &mask)) {
123
0
    maskSurface = mask.GetSurface();
124
0
    maskTransform = mask.GetTransform();
125
0
  }
126
0
127
0
  if (!IsHidden() && !clipExtents.IsEmpty()) {
128
0
    mContentClient->DrawTo(this, aContext->GetDrawTarget(), opacity,
129
0
                           effectiveOperator,
130
0
                           maskSurface, &maskTransform);
131
0
  }
132
0
}
133
134
void
135
BasicPaintedLayer::Validate(LayerManager::DrawPaintedLayerCallback aCallback,
136
                           void* aCallbackData,
137
                           ReadbackProcessor* aReadback)
138
0
{
139
0
  if (!mContentClient) {
140
0
    // This client will have a null Forwarder, which means it will not have
141
0
    // a ContentHost on the other side.
142
0
    mContentClient = new ContentClientBasic(mBackend);
143
0
  }
144
0
145
0
  if (!BasicManager()->IsRetained()) {
146
0
    return;
147
0
  }
148
0
149
0
  nsTArray<ReadbackProcessor::Update> readbackUpdates;
150
0
  if (aReadback && UsedForReadback()) {
151
0
    aReadback->GetPaintedLayerUpdates(this, &readbackUpdates);
152
0
  }
153
0
154
0
  uint32_t flags = 0;
155
0
#ifndef MOZ_WIDGET_ANDROID
156
0
  if (BasicManager()->CompositorMightResample()) {
157
0
    flags |= ContentClient::PAINT_WILL_RESAMPLE;
158
0
  }
159
0
  if (!(flags & ContentClient::PAINT_WILL_RESAMPLE)) {
160
0
    if (MayResample()) {
161
0
      flags |= ContentClient::PAINT_WILL_RESAMPLE;
162
0
    }
163
0
  }
164
0
#endif
165
0
  if (mDrawAtomically) {
166
0
    flags |= ContentClient::PAINT_NO_ROTATION;
167
0
  }
168
0
  PaintState state =
169
0
    mContentClient->BeginPaint(this, flags);
170
0
  SubtractFromValidRegion(state.mRegionToInvalidate);
171
0
172
0
  DrawTarget* target = mContentClient->BorrowDrawTargetForPainting(state);
173
0
  if (target && target->IsValid()) {
174
0
    // The area that became invalid and is visible needs to be repainted
175
0
    // (this could be the whole visible area if our buffer switched
176
0
    // from RGB to RGBA, because we might need to repaint with
177
0
    // subpixel AA)
178
0
    state.mRegionToInvalidate.And(state.mRegionToInvalidate,
179
0
                                  GetLocalVisibleRegion().ToUnknownRegion());
180
0
    SetAntialiasingFlags(this, target);
181
0
182
0
    RenderTraceInvalidateStart(this, "FFFF00", state.mRegionToDraw.GetBounds());
183
0
184
0
    RefPtr<gfxContext> ctx = gfxContext::CreatePreservingTransformOrNull(target);
185
0
    MOZ_ASSERT(ctx); // already checked the target above
186
0
187
0
    PaintBuffer(ctx,
188
0
                state.mRegionToDraw, state.mRegionToDraw, state.mRegionToInvalidate,
189
0
                state.mClip,
190
0
                aCallback, aCallbackData);
191
0
    MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) PaintThebes", this));
192
0
    Mutated();
193
0
    ctx = nullptr;
194
0
    mContentClient->ReturnDrawTarget(target);
195
0
    target = nullptr;
196
0
197
0
    RenderTraceInvalidateEnd(this, "FFFF00");
198
0
  } else {
199
0
    if (target) {
200
0
      mContentClient->ReturnDrawTarget(target);
201
0
      target = nullptr;
202
0
    }
203
0
204
0
    // It's possible that state.mRegionToInvalidate is nonempty here,
205
0
    // if we are shrinking the valid region to nothing. So use mRegionToDraw
206
0
    // instead.
207
0
    NS_WARNING_ASSERTION(
208
0
      state.mRegionToDraw.IsEmpty(),
209
0
      "No context when we have something to draw, resource exhaustion?");
210
0
  }
211
0
212
0
  for (uint32_t i = 0; i < readbackUpdates.Length(); ++i) {
213
0
    ReadbackProcessor::Update& update = readbackUpdates[i];
214
0
    nsIntPoint offset = update.mLayer->GetBackgroundLayerOffset();
215
0
    RefPtr<DrawTarget> dt =
216
0
      update.mLayer->GetSink()->BeginUpdate(update.mUpdateRect + offset,
217
0
                                            update.mSequenceCounter);
218
0
    if (dt) {
219
0
      NS_ASSERTION(GetEffectiveOpacity() == 1.0, "Should only read back opaque layers");
220
0
      NS_ASSERTION(!GetMaskLayer(), "Should only read back layers without masks");
221
0
      dt->SetTransform(dt->GetTransform().PreTranslate(offset.x, offset.y));
222
0
      mContentClient->DrawTo(this, dt, 1.0, CompositionOp::OP_OVER,
223
0
                             nullptr, nullptr);
224
0
      update.mLayer->GetSink()->EndUpdate(update.mUpdateRect + offset);
225
0
    }
226
0
  }
227
0
}
228
229
already_AddRefed<PaintedLayer>
230
BasicLayerManager::CreatePaintedLayer()
231
0
{
232
0
  NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
233
0
234
0
  BackendType backend = gfxPlatform::GetPlatform()->GetDefaultContentBackend();
235
0
236
0
  if (mDefaultTarget) {
237
0
    backend = mDefaultTarget->GetDrawTarget()->GetBackendType();
238
0
  } else if (mType == BLM_WIDGET) {
239
0
    backend = gfxPlatform::GetPlatform()->GetContentBackendFor(LayersBackend::LAYERS_BASIC);
240
0
  }
241
0
242
0
  RefPtr<PaintedLayer> layer = new BasicPaintedLayer(this, backend);
243
0
  return layer.forget();
244
0
}
245
246
} // namespace layers
247
} // namespace mozilla