Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/gfx/layers/client/SingleTiledContentClient.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 "mozilla/layers/SingleTiledContentClient.h"
8
9
#include "ClientTiledPaintedLayer.h"
10
#include "mozilla/Maybe.h"
11
#include "mozilla/UniquePtr.h"
12
13
namespace mozilla {
14
namespace layers {
15
16
17
SingleTiledContentClient::SingleTiledContentClient(ClientTiledPaintedLayer& aPaintedLayer,
18
                                                   ClientLayerManager* aManager)
19
  : TiledContentClient(aManager, "Single")
20
0
{
21
0
  MOZ_COUNT_CTOR(SingleTiledContentClient);
22
0
23
0
  mTiledBuffer = new ClientSingleTiledLayerBuffer(aPaintedLayer, *this, aManager);
24
0
}
25
26
void
27
SingleTiledContentClient::ClearCachedResources()
28
0
{
29
0
  CompositableClient::ClearCachedResources();
30
0
  mTiledBuffer->DiscardBuffers();
31
0
}
32
33
void
34
SingleTiledContentClient::UpdatedBuffer(TiledBufferType aType)
35
0
{
36
0
  mForwarder->UseTiledLayerBuffer(this, mTiledBuffer->GetSurfaceDescriptorTiles());
37
0
}
38
39
/* static */ bool
40
SingleTiledContentClient::ClientSupportsLayerSize(const gfx::IntSize& aSize, ClientLayerManager* aManager)
41
0
{
42
0
  int32_t maxTextureSize = aManager->GetMaxTextureSize();
43
0
  return aSize.width <= maxTextureSize && aSize.height <= maxTextureSize;
44
0
}
45
46
ClientSingleTiledLayerBuffer::ClientSingleTiledLayerBuffer(ClientTiledPaintedLayer& aPaintedLayer,
47
                                                           CompositableClient& aCompositableClient,
48
                                                           ClientLayerManager* aManager)
49
  : ClientTiledLayerBuffer(aPaintedLayer, aCompositableClient)
50
  , mManager(aManager)
51
  , mWasLastPaintProgressive(false)
52
  , mFormat(gfx::SurfaceFormat::UNKNOWN)
53
0
{
54
0
}
55
56
void
57
ClientSingleTiledLayerBuffer::ReleaseTiles()
58
0
{
59
0
  if (!mTile.IsPlaceholderTile()) {
60
0
    mTile.DiscardBuffers();
61
0
  }
62
0
  mTile.SetTextureAllocator(nullptr);
63
0
}
64
65
void
66
ClientSingleTiledLayerBuffer::DiscardBuffers()
67
0
{
68
0
  if (!mTile.IsPlaceholderTile()) {
69
0
    mTile.DiscardFrontBuffer();
70
0
    mTile.DiscardBackBuffer();
71
0
  }
72
0
}
73
74
SurfaceDescriptorTiles
75
ClientSingleTiledLayerBuffer::GetSurfaceDescriptorTiles()
76
0
{
77
0
  InfallibleTArray<TileDescriptor> tiles;
78
0
79
0
  TileDescriptor tileDesc = mTile.GetTileDescriptor();
80
0
  tiles.AppendElement(tileDesc);
81
0
  mTile.mUpdateRect = gfx::IntRect();
82
0
83
0
  return SurfaceDescriptorTiles(mValidRegion,
84
0
                                tiles,
85
0
                                mTilingOrigin,
86
0
                                mSize,
87
0
                                0, 0, 1, 1,
88
0
                                1.0,
89
0
                                mFrameResolution.xScale,
90
0
                                mFrameResolution.yScale,
91
0
                                mWasLastPaintProgressive);
92
0
}
93
94
already_AddRefed<TextureClient>
95
ClientSingleTiledLayerBuffer::GetTextureClient()
96
0
{
97
0
  MOZ_ASSERT(mFormat != gfx::SurfaceFormat::UNKNOWN);
98
0
  return mCompositableClient.CreateTextureClientForDrawing(
99
0
    gfx::ImageFormatToSurfaceFormat(mFormat), mSize, BackendSelector::Content,
100
0
    TextureFlags::DISALLOW_BIGIMAGE | TextureFlags::IMMEDIATE_UPLOAD | TextureFlags::NON_BLOCKING_READ_LOCK);
101
0
}
102
103
void
104
ClientSingleTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion,
105
                                          const nsIntRegion& aPaintRegion,
106
                                          const nsIntRegion& aDirtyRegion,
107
                                          LayerManager::DrawPaintedLayerCallback aCallback,
108
                                          void* aCallbackData,
109
                                          TilePaintFlags aFlags)
110
0
{
111
0
  mWasLastPaintProgressive = !!(aFlags & TilePaintFlags::Progressive);
112
0
  bool asyncPaint = !!(aFlags & TilePaintFlags::Async);
113
0
114
0
  // Compare layer valid region size to current backbuffer size, discard if not matching.
115
0
  gfx::IntSize size = aNewValidRegion.GetBounds().Size();
116
0
  gfx::IntPoint origin = aNewValidRegion.GetBounds().TopLeft();
117
0
  nsIntRegion paintRegion = aPaintRegion;
118
0
119
0
  RefPtr<TextureClient> discardedFrontBuffer = nullptr;
120
0
  RefPtr<TextureClient> discardedFrontBufferOnWhite = nullptr;
121
0
  nsIntRegion discardedValidRegion;
122
0
123
0
  if (mSize != size ||
124
0
      mTilingOrigin != origin) {
125
0
    discardedFrontBuffer = mTile.mFrontBuffer;
126
0
    discardedFrontBufferOnWhite = mTile.mFrontBufferOnWhite;
127
0
    discardedValidRegion = mValidRegion;
128
0
129
0
    TILING_LOG("TILING %p: Single-tile valid region changed. Discarding buffers.\n", &mPaintedLayer);
130
0
    ResetPaintedAndValidState();
131
0
    mSize = size;
132
0
    mTilingOrigin = origin;
133
0
    paintRegion = aNewValidRegion;
134
0
  }
135
0
136
0
  SurfaceMode mode;
137
0
  gfxContentType content = GetContentType(&mode);
138
0
  mFormat = gfxPlatform::GetPlatform()->OptimalFormatForContent(content);
139
0
140
0
  if (mTile.IsPlaceholderTile()) {
141
0
    mTile.SetTextureAllocator(this);
142
0
  }
143
0
144
0
145
0
  if (mManager->AsShadowForwarder()->SupportsTextureDirectMapping()) {
146
0
    AutoTArray<uint64_t, 2> syncTextureSerials;
147
0
    mTile.GetSyncTextureSerials(mode, syncTextureSerials);
148
0
    if (syncTextureSerials.Length() > 0) {
149
0
      mManager->AsShadowForwarder()->SyncTextures(syncTextureSerials);
150
0
    }
151
0
  }
152
0
153
0
  // The dirty region relative to the top-left of the tile.
154
0
  nsIntRegion tileVisibleRegion = aNewValidRegion.MovedBy(-mTilingOrigin);
155
0
  nsIntRegion tileDirtyRegion = paintRegion.MovedBy(-mTilingOrigin);
156
0
157
0
  Maybe<AcquiredBackBuffer> backBuffer =
158
0
    mTile.AcquireBackBuffer(mCompositableClient,
159
0
                            tileDirtyRegion,
160
0
                            tileVisibleRegion,
161
0
                            content,
162
0
                            mode,
163
0
                            aFlags);
164
0
165
0
  if (!backBuffer) {
166
0
    return;
167
0
  }
168
0
169
0
  // Mark the area we need to paint in the back buffer as invalid in the
170
0
  // front buffer as they will become out of sync.
171
0
  mTile.mInvalidFront.OrWith(tileDirtyRegion);
172
0
173
0
  // Add backbuffer's invalid region to the dirty region to be painted.
174
0
  // This will be empty if we were able to copy from the front in to the back.
175
0
  nsIntRegion tileInvalidRegion = mTile.mInvalidBack;
176
0
  tileInvalidRegion.AndWith(tileVisibleRegion);
177
0
178
0
  paintRegion.OrWith(tileInvalidRegion.MovedBy(mTilingOrigin));
179
0
  tileDirtyRegion.OrWith(tileInvalidRegion);
180
0
181
0
  // Mark the region we will be painting and the region we copied from the front buffer as
182
0
  // needing to be uploaded to the compositor
183
0
  mTile.mUpdateRect = tileDirtyRegion.GetBounds().Union(backBuffer->mUpdatedRect);
184
0
185
0
  // If the old frontbuffer was discarded then attempt to copy what we
186
0
  // can from it to the new backbuffer.
187
0
  if (discardedFrontBuffer) {
188
0
    nsIntRegion copyableRegion;
189
0
    copyableRegion.And(aNewValidRegion, discardedValidRegion);
190
0
    copyableRegion.SubOut(aDirtyRegion);
191
0
192
0
    OpenMode readMode = asyncPaint ? OpenMode::OPEN_READ_ASYNC
193
0
                                   : OpenMode::OPEN_READ;
194
0
195
0
    DualTextureClientAutoLock discardedBuffer(discardedFrontBuffer, discardedFrontBufferOnWhite, readMode);
196
0
197
0
    if (discardedBuffer.Succeeded()) {
198
0
      RefPtr<gfx::SourceSurface> discardedSurface = discardedBuffer->Snapshot();
199
0
200
0
      for (auto iter = copyableRegion.RectIter(); !iter.Done(); iter.Next()) {
201
0
        const gfx::IntRect src = iter.Get() - discardedValidRegion.GetBounds().TopLeft();
202
0
        const gfx::IntPoint dest = iter.Get().TopLeft() - mTilingOrigin;
203
0
204
0
        backBuffer->mTarget->CopySurface(discardedSurface, src, dest);
205
0
      }
206
0
207
0
      TILING_LOG("TILING %p: Region copied from discarded frontbuffer %s\n", &mPaintedLayer, Stringify(copyableRegion).c_str());
208
0
209
0
      // We don't need to repaint valid content that was just copied.
210
0
      paintRegion.SubOut(copyableRegion);
211
0
      copyableRegion.MoveBy(-mTilingOrigin);
212
0
      tileDirtyRegion.SubOut(copyableRegion);
213
0
    } else {
214
0
      gfxWarning() << "[Tiling:Client] Failed to aquire the discarded front buffer's draw target";
215
0
    }
216
0
  }
217
0
218
0
  if (mode != SurfaceMode::SURFACE_OPAQUE) {
219
0
    for (auto iter = tileDirtyRegion.RectIter(); !iter.Done(); iter.Next()) {
220
0
      const gfx::Rect drawRect(iter.Get().X(), iter.Get().Y(),
221
0
                               iter.Get().Width(), iter.Get().Height());
222
0
      backBuffer->mTarget->ClearRect(drawRect);
223
0
    }
224
0
  }
225
0
226
0
  // Paint into the target
227
0
  {
228
0
    RefPtr<gfxContext> ctx = gfxContext::CreateOrNull(backBuffer->mTarget);
229
0
    if (!ctx) {
230
0
      gfxDevCrash(gfx::LogReason::InvalidContext) << "SingleTiledContextClient context problem " << gfx::hexa(backBuffer->mTarget);
231
0
      return;
232
0
    }
233
0
    ctx->SetMatrix(ctx->CurrentMatrix().PreTranslate(-mTilingOrigin.x, -mTilingOrigin.y));
234
0
235
0
    aCallback(&mPaintedLayer, ctx, paintRegion, paintRegion, DrawRegionClip::DRAW, nsIntRegion(), aCallbackData);
236
0
  }
237
0
238
0
  if (asyncPaint) {
239
0
    if (!backBuffer->mCapture->IsEmpty()) {
240
0
      UniquePtr<PaintTask> task(new PaintTask());
241
0
      task->mCapture = backBuffer->mCapture;
242
0
      task->mTarget = backBuffer->mBackBuffer;
243
0
      task->mClients = std::move(backBuffer->mTextureClients);
244
0
245
0
      // The target is an alias for the capture, and the paint thread expects
246
0
      // to be the only one with a reference to the capture
247
0
      backBuffer->mTarget = nullptr;
248
0
      backBuffer->mCapture = nullptr;
249
0
250
0
      PaintThread::Get()->QueuePaintTask(std::move(task));
251
0
      mManager->SetQueuedAsyncPaints();
252
0
    }
253
0
  } else {
254
0
    MOZ_ASSERT(backBuffer->mTarget == backBuffer->mBackBuffer);
255
0
    MOZ_ASSERT(!backBuffer->mCapture);
256
0
  }
257
0
258
0
  // The new buffer is now validated, remove the dirty region from it.
259
0
  mTile.mInvalidBack.SubOut(tileDirtyRegion);
260
0
261
0
  backBuffer = Nothing();
262
0
263
0
  mTile.Flip();
264
0
  UnlockTile(mTile);
265
0
266
0
  mValidRegion = aNewValidRegion;
267
0
  mLastPaintSurfaceMode = mode;
268
0
  mLastPaintContentType = content;
269
0
}
270
271
} // namespace layers
272
} // namespace mozilla