Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/gfx/layers/ipc/SharedSurfacesParent.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 "SharedSurfacesParent.h"
8
#include "mozilla/DebugOnly.h"
9
#include "mozilla/layers/SourceSurfaceSharedData.h"
10
#include "mozilla/layers/CompositorThread.h"
11
#include "mozilla/webrender/RenderSharedSurfaceTextureHost.h"
12
#include "mozilla/webrender/RenderThread.h"
13
14
namespace mozilla {
15
namespace layers {
16
17
using namespace mozilla::gfx;
18
19
StaticMutex SharedSurfacesParent::sMutex;
20
StaticAutoPtr<SharedSurfacesParent> SharedSurfacesParent::sInstance;
21
22
SharedSurfacesParent::SharedSurfacesParent()
23
0
{
24
0
}
25
26
SharedSurfacesParent::~SharedSurfacesParent()
27
0
{
28
0
  for (auto i = mSurfaces.Iter(); !i.Done(); i.Next()) {
29
0
    // There may be lingering consumers of the surfaces that didn't get shutdown
30
0
    // yet but since we are here, we know the render thread is finished and we
31
0
    // can unregister everything.
32
0
    wr::RenderThread::Get()->UnregisterExternalImageDuringShutdown(i.Key());
33
0
  }
34
0
}
35
36
/* static */ void
37
SharedSurfacesParent::Initialize()
38
0
{
39
0
  MOZ_ASSERT(NS_IsMainThread());
40
0
  StaticMutexAutoLock lock(sMutex);
41
0
  if (!sInstance) {
42
0
    sInstance = new SharedSurfacesParent();
43
0
  }
44
0
}
45
46
/* static */ void
47
SharedSurfacesParent::Shutdown()
48
0
{
49
0
  // The main thread should blocked on waiting for the render thread to
50
0
  // complete so this should be safe to release off the main thread.
51
0
  MOZ_ASSERT(wr::RenderThread::IsInRenderThread());
52
0
  StaticMutexAutoLock lock(sMutex);
53
0
  sInstance = nullptr;
54
0
}
55
56
/* static */ already_AddRefed<DataSourceSurface>
57
SharedSurfacesParent::Get(const wr::ExternalImageId& aId)
58
0
{
59
0
  StaticMutexAutoLock lock(sMutex);
60
0
  if (!sInstance) {
61
0
    return nullptr;
62
0
  }
63
0
64
0
  RefPtr<SourceSurfaceSharedDataWrapper> surface;
65
0
  sInstance->mSurfaces.Get(wr::AsUint64(aId), getter_AddRefs(surface));
66
0
  return surface.forget();
67
0
}
68
69
/* static */ already_AddRefed<DataSourceSurface>
70
SharedSurfacesParent::Acquire(const wr::ExternalImageId& aId)
71
0
{
72
0
  StaticMutexAutoLock lock(sMutex);
73
0
  if (!sInstance) {
74
0
    return nullptr;
75
0
  }
76
0
77
0
  RefPtr<SourceSurfaceSharedDataWrapper> surface;
78
0
  sInstance->mSurfaces.Get(wr::AsUint64(aId), getter_AddRefs(surface));
79
0
80
0
  if (surface) {
81
0
    DebugOnly<bool> rv = surface->AddConsumer();
82
0
    MOZ_ASSERT(!rv);
83
0
  }
84
0
  return surface.forget();
85
0
}
86
87
/* static */ bool
88
SharedSurfacesParent::Release(const wr::ExternalImageId& aId)
89
0
{
90
0
  StaticMutexAutoLock lock(sMutex);
91
0
  if (!sInstance) {
92
0
    return false;
93
0
  }
94
0
95
0
  uint64_t id = wr::AsUint64(aId);
96
0
  RefPtr<SourceSurfaceSharedDataWrapper> surface;
97
0
  sInstance->mSurfaces.Get(wr::AsUint64(aId), getter_AddRefs(surface));
98
0
  if (!surface) {
99
0
    return false;
100
0
  }
101
0
102
0
  if (surface->RemoveConsumer()) {
103
0
    wr::RenderThread::Get()->UnregisterExternalImage(id);
104
0
    sInstance->mSurfaces.Remove(id);
105
0
  }
106
0
107
0
  return true;
108
0
}
109
110
/* static */ void
111
SharedSurfacesParent::AddSameProcess(const wr::ExternalImageId& aId,
112
                                     SourceSurfaceSharedData* aSurface)
113
0
{
114
0
  MOZ_ASSERT(XRE_IsParentProcess());
115
0
  MOZ_ASSERT(NS_IsMainThread());
116
0
  StaticMutexAutoLock lock(sMutex);
117
0
  if (!sInstance) {
118
0
    return;
119
0
  }
120
0
121
0
  // If the child bridge detects it is in the combined UI/GPU process, then it
122
0
  // will insert a wrapper surface holding the shared memory buffer directly.
123
0
  // This is good because we avoid mapping the same shared memory twice, but
124
0
  // still allow the original surface to be freed and remove the wrapper from
125
0
  // the table when it is no longer needed.
126
0
  RefPtr<SourceSurfaceSharedDataWrapper> surface =
127
0
    new SourceSurfaceSharedDataWrapper();
128
0
  surface->Init(aSurface);
129
0
130
0
  uint64_t id = wr::AsUint64(aId);
131
0
  MOZ_ASSERT(!sInstance->mSurfaces.Contains(id));
132
0
133
0
  RefPtr<wr::RenderSharedSurfaceTextureHost> texture =
134
0
    new wr::RenderSharedSurfaceTextureHost(surface);
135
0
  wr::RenderThread::Get()->RegisterExternalImage(id, texture.forget());
136
0
137
0
  surface->AddConsumer();
138
0
  sInstance->mSurfaces.Put(id, surface);
139
0
}
140
141
/* static */ void
142
SharedSurfacesParent::RemoveSameProcess(const wr::ExternalImageId& aId)
143
0
{
144
0
  MOZ_ASSERT(XRE_IsParentProcess());
145
0
  MOZ_ASSERT(NS_IsMainThread());
146
0
  Release(aId);
147
0
}
148
149
/* static */ void
150
SharedSurfacesParent::DestroyProcess(base::ProcessId aPid)
151
0
{
152
0
  StaticMutexAutoLock lock(sMutex);
153
0
  if (!sInstance) {
154
0
    return;
155
0
  }
156
0
157
0
  // Note that the destruction of a parent may not be cheap if it still has a
158
0
  // lot of surfaces still bound that require unmapping.
159
0
  for (auto i = sInstance->mSurfaces.Iter(); !i.Done(); i.Next()) {
160
0
    SourceSurfaceSharedDataWrapper* surface = i.Data();
161
0
    if (surface->GetCreatorPid() == aPid && surface->RemoveConsumer()) {
162
0
      wr::RenderThread::Get()->UnregisterExternalImage(i.Key());
163
0
      i.Remove();
164
0
    }
165
0
  }
166
0
}
167
168
/* static */ void
169
SharedSurfacesParent::Add(const wr::ExternalImageId& aId,
170
                          const SurfaceDescriptorShared& aDesc,
171
                          base::ProcessId aPid)
172
0
{
173
0
  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
174
0
  MOZ_ASSERT(aPid != base::GetCurrentProcId());
175
0
  StaticMutexAutoLock lock(sMutex);
176
0
  if (!sInstance) {
177
0
    return;
178
0
  }
179
0
180
0
  // Note that the surface wrapper maps in the given handle as read only.
181
0
  RefPtr<SourceSurfaceSharedDataWrapper> surface =
182
0
    new SourceSurfaceSharedDataWrapper();
183
0
  if (NS_WARN_IF(!surface->Init(aDesc.size(), aDesc.stride(),
184
0
                                aDesc.format(), aDesc.handle(),
185
0
                                aPid))) {
186
0
    return;
187
0
  }
188
0
189
0
  uint64_t id = wr::AsUint64(aId);
190
0
  MOZ_ASSERT(!sInstance->mSurfaces.Contains(id));
191
0
192
0
  RefPtr<wr::RenderSharedSurfaceTextureHost> texture =
193
0
    new wr::RenderSharedSurfaceTextureHost(surface);
194
0
  wr::RenderThread::Get()->RegisterExternalImage(id, texture.forget());
195
0
196
0
  surface->AddConsumer();
197
0
  sInstance->mSurfaces.Put(id, surface.forget());
198
0
}
199
200
/* static */ void
201
SharedSurfacesParent::Remove(const wr::ExternalImageId& aId)
202
0
{
203
0
  DebugOnly<bool> rv = Release(aId);
204
0
  MOZ_ASSERT(rv);
205
0
}
206
207
} // namespace layers
208
} // namespace mozilla