1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 /// \file LayerStackRegistry.cpp
25
26 #include "pxr/pxr.h"
27 #include "pxr/usd/pcp/layerStackRegistry.h"
28 #include "pxr/usd/pcp/layerStack.h"
29 #include "pxr/usd/pcp/layerStackIdentifier.h"
30
31 #include "pxr/usd/ar/resolver.h"
32 #include "pxr/usd/sdf/layerUtils.h"
33 #include "pxr/base/tf/diagnostic.h"
34 #include "pxr/base/tf/staticData.h"
35
36 #include <tbb/queuing_rw_mutex.h>
37
38 #include <boost/unordered_map.hpp>
39
40 #include <algorithm>
41 #include <utility>
42
43 using std::pair;
44 using std::make_pair;
45
46 PXR_NAMESPACE_OPEN_SCOPE
47
48 class Pcp_LayerStackRegistryData {
49 public:
Pcp_LayerStackRegistryData(const std::string & fileFormatTarget_,bool isUsd)50 Pcp_LayerStackRegistryData(
51 const std::string& fileFormatTarget_, bool isUsd)
52 : fileFormatTarget(fileFormatTarget_)
53 , isUsd(isUsd)
54 { }
55
56 typedef SdfLayerHandleVector Layers;
57 typedef PcpLayerStackPtrVector LayerStacks;
58 typedef boost::unordered_map<PcpLayerStackIdentifier, PcpLayerStackPtr>
59 IdentifierToLayerStack;
60 typedef boost::unordered_map<SdfLayerHandle, LayerStacks>
61 LayerToLayerStacks;
62 typedef boost::unordered_map<PcpLayerStackPtr, Layers>
63 LayerStackToLayers;
64
65 typedef boost::unordered_map<std::string, LayerStacks>
66 MutedLayerIdentifierToLayerStacks;
67 typedef boost::unordered_map<PcpLayerStackPtr, std::set<std::string> >
68 LayerStackToMutedLayerIdentifiers;
69
70 IdentifierToLayerStack identifierToLayerStack;
71 LayerToLayerStacks layerToLayerStacks;
72 LayerStackToLayers layerStackToLayers;
73 MutedLayerIdentifierToLayerStacks mutedLayerIdentifierToLayerStacks;
74 LayerStackToMutedLayerIdentifiers layerStackToMutedLayerIdentifiers;
75
76 const PcpLayerStackPtrVector empty;
77 const std::string fileFormatTarget;
78 bool isUsd;
79 Pcp_MutedLayers mutedLayers;
80
81 tbb::queuing_rw_mutex mutex;
82 };
83
84 Pcp_LayerStackRegistryRefPtr
New(const std::string & fileFormatTarget,bool isUsd)85 Pcp_LayerStackRegistry::New(const std::string& fileFormatTarget, bool isUsd)
86 {
87 return TfCreateRefPtr(new Pcp_LayerStackRegistry(fileFormatTarget, isUsd));
88 }
89
Pcp_LayerStackRegistry(const std::string & fileFormatTarget,bool isUsd)90 Pcp_LayerStackRegistry::Pcp_LayerStackRegistry(
91 const std::string& fileFormatTarget, bool isUsd)
92 : _data(new Pcp_LayerStackRegistryData(fileFormatTarget, isUsd))
93 {
94 // Do nothing
95 }
96
~Pcp_LayerStackRegistry()97 Pcp_LayerStackRegistry::~Pcp_LayerStackRegistry()
98 {
99 // Do nothing
100 }
101
102 void
MuteAndUnmuteLayers(const SdfLayerHandle & anchorLayer,std::vector<std::string> * layersToMute,std::vector<std::string> * layersToUnmute)103 Pcp_LayerStackRegistry::MuteAndUnmuteLayers(
104 const SdfLayerHandle& anchorLayer,
105 std::vector<std::string>* layersToMute,
106 std::vector<std::string>* layersToUnmute)
107 {
108 _data->mutedLayers.MuteAndUnmuteLayers(
109 anchorLayer, layersToMute, layersToUnmute);
110 }
111
112 const std::vector<std::string>&
GetMutedLayers() const113 Pcp_LayerStackRegistry::GetMutedLayers() const
114 {
115 return _data->mutedLayers.GetMutedLayers();
116 }
117
118 bool
IsLayerMuted(const SdfLayerHandle & anchorLayer,const std::string & layerIdentifier,std::string * canonicalSublayerId) const119 Pcp_LayerStackRegistry::IsLayerMuted(const SdfLayerHandle& anchorLayer,
120 const std::string& layerIdentifier,
121 std::string* canonicalSublayerId) const
122 {
123 return _data->mutedLayers.IsLayerMuted(
124 anchorLayer, layerIdentifier, canonicalSublayerId);
125 }
126
127 const PcpLayerStackPtrVector&
FindAllUsingMutedLayer(const std::string & layerId) const128 Pcp_LayerStackRegistry::FindAllUsingMutedLayer(const std::string& layerId) const
129 {
130 tbb::queuing_rw_mutex::scoped_lock lock(_data->mutex, /*write=*/false);
131 const auto i = _data->mutedLayerIdentifierToLayerStacks.find(layerId);
132 return i != _data->mutedLayerIdentifierToLayerStacks.end() ?
133 i->second : _data->empty;
134 }
135
136 PcpLayerStackRefPtr
FindOrCreate(const PcpLayerStackIdentifier & identifier,PcpErrorVector * allErrors)137 Pcp_LayerStackRegistry::FindOrCreate(const PcpLayerStackIdentifier& identifier,
138 PcpErrorVector *allErrors)
139 {
140 // Can only create layer stacks for valid identifiers so if the identifier
141 // is invalid we can't have an entry for it.
142 if (!identifier) {
143 TF_CODING_ERROR("Cannot build layer stack with null rootLayer");
144 return TfNullPtr;
145 }
146
147 tbb::queuing_rw_mutex::scoped_lock lock(_data->mutex, /*write=*/false);
148 PcpLayerStackRefPtr refLayerStack;
149
150 if (const PcpLayerStackPtr & layerStack = _Find(identifier)) {
151 refLayerStack = TfCreateRefPtrFromProtectedWeakPtr(layerStack);
152 }
153 if (!refLayerStack) {
154 lock.release();
155
156 PcpLayerStackRefPtr createdLayerStack =
157 TfCreateRefPtr(new PcpLayerStack(
158 identifier, _GetFileFormatTarget(), _GetMutedLayers(),
159 _IsUsd()));
160
161 // Take the lock and check again for an existing layer stack, or
162 // install the one we just created.
163 lock.acquire(_data->mutex);
164 if (const PcpLayerStackPtr & layerStack = _Find(identifier)) {
165 refLayerStack = TfCreateRefPtrFromProtectedWeakPtr(layerStack);
166 }
167 if (!refLayerStack) {
168 // No existing entry, or it is being deleted. Add the one we just
169 // create to the map.
170 refLayerStack = createdLayerStack;
171 _data->identifierToLayerStack[identifier] = refLayerStack;
172 // Also give it a link back to us so it can remove itself upon
173 // destruction, and install its layers into our structures.
174 refLayerStack->_registry = TfCreateWeakPtr(this);
175 _SetLayers(get_pointer(refLayerStack));
176 lock.release();
177
178 // Return errors from newly computed layer stacks.
179 PcpErrorVector errors = refLayerStack->GetLocalErrors();
180 allErrors->insert(allErrors->end(), errors.begin(), errors.end());
181 }
182 }
183
184 return refLayerStack;
185 }
186
187 PcpLayerStackPtr
Find(const PcpLayerStackIdentifier & identifier) const188 Pcp_LayerStackRegistry::Find(const PcpLayerStackIdentifier& identifier) const
189 {
190 tbb::queuing_rw_mutex::scoped_lock lock(_data->mutex, /*write=*/false);
191 return _Find(identifier);
192 }
193
194 PcpLayerStackPtr
_Find(const PcpLayerStackIdentifier & identifier) const195 Pcp_LayerStackRegistry::_Find(const PcpLayerStackIdentifier& identifier) const
196 {
197 auto iter = _data->identifierToLayerStack.find(identifier);
198 return (iter != _data->identifierToLayerStack.end()) ?
199 iter->second : PcpLayerStackPtr();
200 }
201
202 bool
Contains(const PcpLayerStackPtr & layerStack) const203 Pcp_LayerStackRegistry::Contains(const PcpLayerStackPtr& layerStack) const
204 {
205 auto ptr = get_pointer(layerStack);
206 return ptr && get_pointer(ptr->_registry) == this;
207 }
208
209 const PcpLayerStackPtrVector&
FindAllUsingLayer(const SdfLayerHandle & layer) const210 Pcp_LayerStackRegistry::FindAllUsingLayer(const SdfLayerHandle& layer) const
211 {
212 tbb::queuing_rw_mutex::scoped_lock lock(_data->mutex, /*write=*/false);
213 auto i = _data->layerToLayerStacks.find(layer);
214 return i != _data->layerToLayerStacks.end() ? i->second : _data->empty;
215 }
216
217 std::vector<PcpLayerStackPtr>
GetAllLayerStacks() const218 Pcp_LayerStackRegistry::GetAllLayerStacks() const
219 {
220 tbb::queuing_rw_mutex::scoped_lock lock(_data->mutex, /*write=*/false);
221 std::vector<PcpLayerStackPtr> result;
222 result.reserve(_data->identifierToLayerStack.size());
223 TF_FOR_ALL(i, _data->identifierToLayerStack) {
224 TF_VERIFY(i->second, "Unexpected dead layer stack %s",
225 TfStringify(i->first).c_str());
226 result.push_back(i->second);
227 }
228 return result;
229 }
230
231 void
ForEachLayerStack(const TfFunctionRef<void (const PcpLayerStackPtr &)> & fn)232 Pcp_LayerStackRegistry::ForEachLayerStack(
233 const TfFunctionRef<void(const PcpLayerStackPtr&)>& fn)
234 {
235 // Copy all layer stacks so that we can run the callback
236 // without holding a read lock on the layer registry.
237 const std::vector<PcpLayerStackPtr> layerStacks = GetAllLayerStacks();
238 for (const PcpLayerStackPtr& layerStack : layerStacks) {
239 fn(layerStack);
240 }
241 }
242
243 ////////////////////////////////////////////////////////////////////////
244 // Private helper methods.
245
246 void
_SetLayersAndRemove(const PcpLayerStackIdentifier & identifier,const PcpLayerStack * layerStack)247 Pcp_LayerStackRegistry::_SetLayersAndRemove(
248 const PcpLayerStackIdentifier& identifier,
249 const PcpLayerStack *layerStack)
250 {
251 tbb::queuing_rw_mutex::scoped_lock lock(_data->mutex, /*write=*/true);
252
253 Pcp_LayerStackRegistryData::IdentifierToLayerStack::const_iterator i =
254 _data->identifierToLayerStack.find(identifier);
255 // It's possible that layerStack has already been removed from the
256 // map if a FindOrCreate call intercedes between the moment when the
257 // layer stack's ref count drops to zero and the time the layer stack
258 // destructor is called (which is how we get into this method).
259 // Always call _SetLayers to clear this (now empty) layer stack's
260 // pointer from the maps inside _data, even if a new layer stack with the
261 // same identifier has already been added to the identifierToLayerStack
262 // map.
263 _SetLayers(layerStack);
264 if (i != _data->identifierToLayerStack.end() &&
265 i->second.operator->() == layerStack) {
266 _data->identifierToLayerStack.erase(identifier);
267 }
268 }
269
270 void
_SetLayers(const PcpLayerStack * layerStack)271 Pcp_LayerStackRegistry::_SetLayers(const PcpLayerStack* layerStack)
272 {
273 PcpLayerStackPtr layerStackPtr = TfCreateNonConstWeakPtr(layerStack);
274
275 // Get the layers for the layer stack.
276 Pcp_LayerStackRegistryData::Layers& layers =
277 _data->layerStackToLayers[layerStackPtr];
278
279 // Remove layer stack from the table entry for each layer in
280 // the layer stack.
281 for (const auto& layer : layers) {
282 Pcp_LayerStackRegistryData::LayerStacks& layerStacks =
283 _data->layerToLayerStacks[layer];
284 layerStacks.erase(std::find(layerStacks.begin(),
285 layerStacks.end(), layerStackPtr));
286 }
287
288 // Save the layers for the layer stack.
289 const SdfLayerRefPtrVector& newLayers = layerStack->GetLayers();
290 if (newLayers.empty()) {
291 // Don't leave empty entries hanging around.
292 _data->layerStackToLayers.erase(layerStackPtr);
293 } else {
294 layers.assign(newLayers.begin(), newLayers.end());
295 }
296
297 // Add the layer stack for each layer in the layer stack.
298 for (const auto& layer : newLayers) {
299 _data->layerToLayerStacks[layer].push_back(layerStackPtr);
300 }
301
302 // Also store mappings from layer stack <-> muted layers in
303 // the layer stack.
304 std::set<std::string>* mutedLayerIdentifiers = TfMapLookupPtr(
305 _data->layerStackToMutedLayerIdentifiers, layerStackPtr);
306
307 if (mutedLayerIdentifiers) {
308 for (const auto& layerId : *mutedLayerIdentifiers) {
309 Pcp_LayerStackRegistryData::LayerStacks& layerStacks =
310 _data->mutedLayerIdentifierToLayerStacks[layerId];
311 layerStacks.erase(std::find(layerStacks.begin(),
312 layerStacks.end(), layerStackPtr));
313 }
314 }
315
316 const std::set<std::string>& newMutedLayers = layerStack->GetMutedLayers();
317 if (newMutedLayers.empty()) {
318 if (mutedLayerIdentifiers) {
319 // Don't leave empty entries hanging around.
320 _data->layerStackToMutedLayerIdentifiers.erase(layerStackPtr);
321 }
322 }
323 else {
324 if (!mutedLayerIdentifiers) {
325 mutedLayerIdentifiers =
326 &_data->layerStackToMutedLayerIdentifiers[layerStackPtr];
327 }
328 *mutedLayerIdentifiers = std::set<std::string>(
329 newMutedLayers.begin(), newMutedLayers.end());
330 }
331
332 for (const auto& mutedLayer : newMutedLayers) {
333 _data->mutedLayerIdentifierToLayerStacks[mutedLayer]
334 .push_back(layerStackPtr);
335 }
336 }
337
338 const std::string&
_GetFileFormatTarget() const339 Pcp_LayerStackRegistry::_GetFileFormatTarget() const
340 {
341 return _data->fileFormatTarget;
342 }
343
344 bool
_IsUsd() const345 Pcp_LayerStackRegistry::_IsUsd() const
346 {
347 return _data->isUsd;
348 }
349
350 const Pcp_MutedLayers&
_GetMutedLayers() const351 Pcp_LayerStackRegistry::_GetMutedLayers() const
352 {
353 return _data->mutedLayers;
354 }
355
356 // ------------------------------------------------------------
357
358 namespace
359 {
360 std::string
_GetCanonicalLayerId(const SdfLayerHandle & anchorLayer,const std::string & layerId)361 _GetCanonicalLayerId(const SdfLayerHandle& anchorLayer,
362 const std::string& layerId)
363 {
364 #if AR_VERSION == 1
365 const std::string computedLayerId =
366 SdfComputeAssetPathRelativeToLayer(anchorLayer, layerId);
367 if (computedLayerId.empty()) {
368 return layerId;
369 }
370
371 if (SdfLayer::IsAnonymousLayerIdentifier(computedLayerId)) {
372 return computedLayerId;
373 }
374
375 ArResolver& resolver = ArGetResolver();
376
377 std::string canonicalPath = computedLayerId;
378 if (resolver.IsSearchPath(canonicalPath)) {
379 std::string resolvedSearchPath = resolver.Resolve(canonicalPath);
380 if (!resolvedSearchPath.empty()) {
381 canonicalPath.swap(resolvedSearchPath);
382 }
383 }
384
385 canonicalPath = resolver.ComputeRepositoryPath(canonicalPath);
386 return canonicalPath.empty() ? computedLayerId : canonicalPath;
387 #else
388 if (SdfLayer::IsAnonymousLayerIdentifier(layerId)) {
389 return layerId;
390 }
391
392 // XXX:
393 // We may ultimately want to use the resolved path here but that's
394 // possibly a bigger change and there are questions about what happens if
395 // the muted path doesn't resolve to an existing asset and how/when to
396 // invalidate the resolved paths stored in the Pcp_MutedLayers object.
397 return ArGetResolver().CreateIdentifier(
398 layerId, anchorLayer->GetResolvedPath());
399 #endif
400 }
401 }
402
403 const std::vector<std::string>&
GetMutedLayers() const404 Pcp_MutedLayers::GetMutedLayers() const
405 {
406 return _layers;
407 }
408
409 void
MuteAndUnmuteLayers(const SdfLayerHandle & anchorLayer,std::vector<std::string> * layersToMute,std::vector<std::string> * layersToUnmute)410 Pcp_MutedLayers::MuteAndUnmuteLayers(const SdfLayerHandle& anchorLayer,
411 std::vector<std::string>* layersToMute,
412 std::vector<std::string>* layersToUnmute)
413 {
414 std::vector<std::string> mutedLayers, unmutedLayers;
415
416 for (const auto& layerToMute : *layersToMute) {
417 const std::string canonicalId =
418 _GetCanonicalLayerId(anchorLayer, layerToMute);
419
420 const auto layerIt = std::lower_bound(
421 _layers.begin(), _layers.end(), canonicalId);
422 if (layerIt == _layers.end() || *layerIt != canonicalId) {
423 _layers.insert(layerIt, canonicalId);
424 mutedLayers.push_back(canonicalId);
425 }
426 }
427
428 for (const auto& layerToUnmute : *layersToUnmute) {
429 const std::string canonicalId =
430 _GetCanonicalLayerId(anchorLayer, layerToUnmute);
431
432 const auto layerIt = std::lower_bound(
433 _layers.begin(), _layers.end(), canonicalId);
434 if (layerIt != _layers.end() && *layerIt == canonicalId) {
435 _layers.erase(layerIt);
436 unmutedLayers.push_back(canonicalId);
437 }
438 }
439
440 layersToMute->swap(mutedLayers);
441 layersToUnmute->swap(unmutedLayers);
442 }
443
444 bool
IsLayerMuted(const SdfLayerHandle & anchorLayer,const std::string & layerId,std::string * canonicalLayerId) const445 Pcp_MutedLayers::IsLayerMuted(const SdfLayerHandle& anchorLayer,
446 const std::string& layerId,
447 std::string* canonicalLayerId) const
448 {
449 if (_layers.empty()) {
450 return false;
451 }
452
453 std::string canonicalId = _GetCanonicalLayerId(anchorLayer, layerId);
454 if (std::binary_search(_layers.begin(), _layers.end(), canonicalId)) {
455 if (canonicalLayerId) {
456 canonicalLayerId->swap(canonicalId);
457 }
458 return true;
459 }
460 return false;
461 }
462
463 PXR_NAMESPACE_CLOSE_SCOPE
464