Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/gfx/layers/SourceSurfaceSharedData.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 "SourceSurfaceSharedData.h"
8
9
#include "mozilla/Likely.h"
10
#include "mozilla/Types.h" // for decltype
11
#include "mozilla/layers/SharedSurfacesChild.h"
12
13
#include "base/process_util.h"
14
15
#ifdef DEBUG
16
/**
17
 * If defined, this makes SourceSurfaceSharedData::Finalize memory protect the
18
 * underlying shared buffer in the producing process (the content or UI
19
 * process). Given flushing the page table is expensive, and its utility is
20
 * predominantly diagnostic (in case of overrun), turn it off by default.
21
 */
22
#define SHARED_SURFACE_PROTECT_FINALIZED
23
#endif
24
25
namespace mozilla {
26
namespace gfx {
27
28
bool
29
SourceSurfaceSharedDataWrapper::Init(const IntSize& aSize,
30
                                     int32_t aStride,
31
                                     SurfaceFormat aFormat,
32
                                     const SharedMemoryBasic::Handle& aHandle,
33
                                     base::ProcessId aCreatorPid)
34
0
{
35
0
  MOZ_ASSERT(!mBuf);
36
0
  mSize = aSize;
37
0
  mStride = aStride;
38
0
  mFormat = aFormat;
39
0
  mCreatorPid = aCreatorPid;
40
0
41
0
  size_t len = GetAlignedDataLength();
42
0
  mBuf = MakeAndAddRef<SharedMemoryBasic>();
43
0
  if (NS_WARN_IF(!mBuf->SetHandle(aHandle, ipc::SharedMemory::RightsReadOnly)) ||
44
0
      NS_WARN_IF(!mBuf->Map(len))) {
45
0
    mBuf = nullptr;
46
0
    return false;
47
0
  }
48
0
49
0
  mBuf->CloseHandle();
50
0
  return true;
51
0
}
52
53
void
54
SourceSurfaceSharedDataWrapper::Init(SourceSurfaceSharedData* aSurface)
55
0
{
56
0
  MOZ_ASSERT(!mBuf);
57
0
  MOZ_ASSERT(aSurface);
58
0
  mSize = aSurface->mSize;
59
0
  mStride = aSurface->mStride;
60
0
  mFormat = aSurface->mFormat;
61
0
  mCreatorPid = base::GetCurrentProcId();
62
0
  mBuf = aSurface->mBuf;
63
0
}
64
65
bool
66
SourceSurfaceSharedData::Init(const IntSize &aSize,
67
                              int32_t aStride,
68
                              SurfaceFormat aFormat,
69
                              bool aShare /* = true */)
70
0
{
71
0
  mSize = aSize;
72
0
  mStride = aStride;
73
0
  mFormat = aFormat;
74
0
75
0
  size_t len = GetAlignedDataLength();
76
0
  mBuf = new SharedMemoryBasic();
77
0
  if (NS_WARN_IF(!mBuf->Create(len)) ||
78
0
      NS_WARN_IF(!mBuf->Map(len))) {
79
0
    mBuf = nullptr;
80
0
    return false;
81
0
  }
82
0
83
0
  if (aShare) {
84
0
    layers::SharedSurfacesChild::Share(this);
85
0
  }
86
0
87
0
  return true;
88
0
}
89
90
void
91
SourceSurfaceSharedData::GuaranteePersistance()
92
0
{
93
0
  // Shared memory is not unmapped until we release SourceSurfaceSharedData.
94
0
}
95
96
void
97
SourceSurfaceSharedData::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
98
                                                size_t& aHeapSizeOut,
99
                                                size_t& aNonHeapSizeOut,
100
                                                size_t& aExtHandlesOut) const
101
0
{
102
0
  MutexAutoLock lock(mMutex);
103
0
  if (mBuf) {
104
0
    aNonHeapSizeOut += GetAlignedDataLength();
105
0
  }
106
0
  if (!mClosed) {
107
0
    ++aExtHandlesOut;
108
0
  }
109
0
}
110
111
uint8_t*
112
SourceSurfaceSharedData::GetDataInternal() const
113
0
{
114
0
  mMutex.AssertCurrentThreadOwns();
115
0
116
0
  // If we have an old buffer lingering, it is because we get reallocated to
117
0
  // get a new handle to share, but there were still active mappings.
118
0
  if (MOZ_UNLIKELY(mOldBuf)) {
119
0
    MOZ_ASSERT(mMapCount > 0);
120
0
    MOZ_ASSERT(mFinalized);
121
0
    return static_cast<uint8_t*>(mOldBuf->memory());
122
0
  }
123
0
  return static_cast<uint8_t*>(mBuf->memory());
124
0
}
125
126
nsresult
127
SourceSurfaceSharedData::ShareToProcess(base::ProcessId aPid,
128
                                        SharedMemoryBasic::Handle& aHandle)
129
0
{
130
0
  MutexAutoLock lock(mMutex);
131
0
  MOZ_ASSERT(mHandleCount > 0);
132
0
133
0
  if (mClosed) {
134
0
    return NS_ERROR_NOT_AVAILABLE;
135
0
  }
136
0
137
0
  bool shared = mBuf->ShareToProcess(aPid, &aHandle);
138
0
  if (MOZ_UNLIKELY(!shared)) {
139
0
    return NS_ERROR_FAILURE;
140
0
  }
141
0
142
0
  return NS_OK;
143
0
}
144
145
void
146
SourceSurfaceSharedData::CloseHandleInternal()
147
0
{
148
0
  mMutex.AssertCurrentThreadOwns();
149
0
150
0
  if (mClosed) {
151
0
    MOZ_ASSERT(mHandleCount == 0);
152
0
    MOZ_ASSERT(mShared);
153
0
    return;
154
0
  }
155
0
156
0
  if (mShared) {
157
0
    mBuf->CloseHandle();
158
0
    mClosed = true;
159
0
  }
160
0
}
161
162
bool
163
SourceSurfaceSharedData::ReallocHandle()
164
0
{
165
0
  MutexAutoLock lock(mMutex);
166
0
  MOZ_ASSERT(mHandleCount > 0);
167
0
  MOZ_ASSERT(mClosed);
168
0
169
0
  if (NS_WARN_IF(!mFinalized)) {
170
0
    // We haven't finished populating the surface data yet, which means we are
171
0
    // out of luck, as we have no means of synchronizing with the producer to
172
0
    // write new data to a new buffer. This should be fairly rare, caused by a
173
0
    // crash in the GPU process, while we were decoding an image.
174
0
    return false;
175
0
  }
176
0
177
0
  size_t len = GetAlignedDataLength();
178
0
  RefPtr<SharedMemoryBasic> buf = new SharedMemoryBasic();
179
0
  if (NS_WARN_IF(!buf->Create(len)) ||
180
0
      NS_WARN_IF(!buf->Map(len))) {
181
0
    return false;
182
0
  }
183
0
184
0
  size_t copyLen = GetDataLength();
185
0
  memcpy(buf->memory(), mBuf->memory(), copyLen);
186
#ifdef SHARED_SURFACE_PROTECT_FINALIZED
187
  buf->Protect(static_cast<char*>(buf->memory()), len, RightsRead);
188
#endif
189
190
0
  if (mMapCount > 0 && !mOldBuf) {
191
0
    mOldBuf = std::move(mBuf);
192
0
  }
193
0
  mBuf = std::move(buf);
194
0
  mClosed = false;
195
0
  mShared = false;
196
0
  return true;
197
0
}
198
199
void
200
SourceSurfaceSharedData::Finalize()
201
0
{
202
0
  MutexAutoLock lock(mMutex);
203
0
  MOZ_ASSERT(!mFinalized);
204
0
205
#ifdef SHARED_SURFACE_PROTECT_FINALIZED
206
  size_t len = GetAlignedDataLength();
207
  mBuf->Protect(static_cast<char*>(mBuf->memory()), len, RightsRead);
208
#endif
209
210
0
  mFinalized = true;
211
0
}
212
213
} // namespace gfx
214
} // namespace mozilla